How dot notation automatically creates a nested structure

an article added by: Amanda Baker at 04022008


In: Root » Computers and technology » Programming » How dot notation automatically creates a nested structure

French Spanish Portuguese Italian German Japanese Chinese Korean Russian Arabic

Until now, you’ve created structures only by using StructNew(). You can also create structures just by using dot notation, as follows:

<cfset aNewStruct.SomeKey.SomeValue = 1>

That line creates a structure named aNewStruct with a substructure named SomeKey that has an element named SomeValue with a value of 1. Notice that the names of all newly created structures and keys are all uppercase, regardless of the capitalization that you use in the code. As convenient as this method may seem, it does have a drawback. Consider the following snippet:

<cfset aNewStruct = StructNew()>
   <cfset aNewStruct.myKey = 2>
   <cfset aNewStruct.yourKey = 3>

After running the preceding snippet, two new keys, named myKey and yourKey, are created. Suppose that you now attempt to call the following snippet to create a nested structure named myKey:

<cfset aNewStruct.myKey.subKey = 4>

If the previous line had worked, it would have overwritten the previous simple value of myKey with a substructure named myKey. Fortunately, however, attempting to overwrite a simple key with a substructure throws an error in ColdFusion MX. You do face a limitation in creating structure keys by using this method. ColdFusion MX can create nested structures only up to three levels deep in a single call, as in this example:

<cfset a = StructNew()>
   <cfset a.b.c.d = “some value”>

Attempting to create a key more than three levels deep gives you unexpected results. ColdFusion ignores all but the last three keys. Running the following code, for example, outputs “some value”:

<cfset a = StructNew()>
   <cfset a.b.c.d.e.f.g = “some value”>
   <cfoutput>
   #a.e.f.g#
   </cfoutput>

You can, however, create structures nested as deeply as you want as long as you don’t attempt to go more than three levels deeper than currently exists. Sometimes data is useful only if it is sorted in a specific order. Although this is easy to do with tabular data in a database, sorting data in a structure takes a little more understanding and effort. Say that you have a structure containing the prices per pound of different fruits, as following:

<cfset FruitCosts = StructNew()>
   <cfset FruitCosts[“Oranges”] = 1.99>
   <cfset FruitCosts[“Apples”] = 1.50>
   <cfset FruitCosts[“Peaches”] = 1.75>
   <cfset FruitCosts[“Cherries”] = 2.25>
   <cfset FruitCosts[“Lemons”] = 1.65>

You can loop over these prices and output them by using the code.

<cfoutput>
   <cfloop collection=”#FruitCosts#” item=”Fruit”>
   #Fruit#: #FruitCosts[Fruit]# / lb.<br>
   </cfloop>
 </cfoutput>

The problem here is that structures don’t have any kind of inherent order. Structure keys are stored in an internal order that only ColdFusion Server understands, and if you loop over the structure, that’s the order that you see. The order in which you insert the keys doesn’t even matter. StructSort() returns an array of key names sorted by their values (not their key names). The code uses StructSort() to put the fruit costs out in order.

<cfset keyArray = StructSort(FruitCosts, “numeric”, “asc”)>
   <cfoutput>
   <cfloop from=”1” to=”#ArrayLen(keyArray)#” index=”i”>
   #keyArray[i]#: #FruitCosts[keyArray[i]]# / lb.<br>
   </cfloop>
 </cfoutput>

The biggest difference between the codes is the approach that each takes to looping over the structure. In the first one, we just use a standard collection loop, relying on whatever order ColdFusion stored the structure in. In the second one, we call StructSort() first, which returns an array of key names that look as follows:

1: Apples
   2: Lemons
   3: Peaches
   4: Oranges
 5: Cherries

These elements still may not seem to be in any particular order, but look at the following prices associated with each element (although the values in parentheses are not actually part of the array):

1: Apples (1.50)
   2: Lemons (1.65)
   3: Peaches (1.75)
   4: Oranges (1.99)
 5: Cherries (2.25)

Although the key names appear in the array, the values remain back in the structure. After calling StructSort(), the code loops through keyArray, which contains the sorted key names. During this loop, keyArray[i] contains the current key name, which can in turn be used to supply the key name to the FruitCosts structure. If you follow the ColdFusion processing engine along step-by-step, the resolution of this reference is as follows:

Step 1: #FruitCosts[keyArray[i]]#
   Step 2: #FruitCosts[keyArray[1]]#
   Step 3: #FruitCosts[“Apples”]#
 Result: 1.50

But what if you want to sort by a key in a nested structure? We’ve modified the FruitCosts structure from earlier in the article by using the following code:

<cfset FruitCosts = StructNew()>
   <cfset FruitCosts[“Oranges”] = StructNew()>
   <cfset FruitCosts[“Oranges”][“lb”] = 1.99>
   <cfset FruitCosts[“Oranges”][“sack”] = 15.50>
   <cfset FruitCosts[“Apples”] = StructNew()>
   <cfset FruitCosts[“Apples”][“lb”] = 1.50>
   <cfset FruitCosts[“Apples”][“sack”] = 13.00>
   <cfset FruitCosts[“Peaches”] = StructNew()>
   <cfset FruitCosts[“Peaches”][“lb”] = 1.75>
   <cfset FruitCosts[“Peaches”][“sack”] = 16.25>
   <cfset FruitCosts[“Cherries”] = StructNew()>
   <cfset FruitCosts[“Cherries”][“lb”] = 2.25>
   <cfset FruitCosts[“Cherries”][“sack”] = 14.00>
   <cfset FruitCosts[“Lemons”] = StructNew()>
   <cfset FruitCosts[“Lemons”][“lb”] = 1.65>
   <cfset FruitCosts[“Lemons”][“sack”] = 15.00>

Each element in the FruitCosts structure is a substructure containing two keys: “lb” (price per pound) and “sack” (price per sack). So now that you have this set of nested structures, how do you sort by price per pound? A fourth attribute of StructSort()describes a dot path to the sort value, as shown in the code.

<cfset keyArray = StructSort(FruitCosts, “numeric”, “asc”, “lb”)>
   <cfoutput>
   <cfloop from=”1” to=”#ArrayLen(keyArray)#” index=”i”>
   #keyArray[i]#: #FruitCosts[keyArray[i]].lb# / lb.<br>
   </cfloop>
 </cfoutput>

The good thing about this method is that you can very easily switch to sorting by price per sack, as shown in the code.

<cfset keyArray = StructSort(FruitCosts, “numeric”, “asc”, “sack”)>
   <cfoutput>
   <cfloop from=”1” to=”#ArrayLen(keyArray)#” index=”i”>
   #keyArray[i]#: #FruitCosts[keyArray[i]].sack# / sack.<br>
   </cfloop>
 </cfoutput>

You can sort by a key any number of levels deep by adding elements to the dot path:

<cfset keyArray = StructSort(FruitCosts, “numeric”, “asc”,
   “sack.10lb.fresh”)>

Be aware that, if the specified subkey doesn’t exist for every top-level element in the main structure, ColdFusion throws an error.

legal disclaimer

Our website is not responsible for the information contained by this article. Web-articles is a free articles resource.
Suggestion: If you need fresh, daily updated content for your website, feel free to use our service. Click here for more information.

related articles

1. Building the company edit action template
The code in CompanyEditAction.cfm is like the code in CompanyAddAction.cfm, but the edit action updates rather than inserts. Create a file named CompanyEditAction.cfm inside the Ch02 directory, type the code into the file’s editing window, and save the file. <cfquery name=”UpdateCompany” datasource=”#Request.MainDSN#”> UPDATE Company SET CompanyName = ‘#Trim(Form.CompanyName)#’, Address = ‘#Trim(Form.Address)#’, City = ‘#Trim(Form.City)...

2. Adding a New Employee to the Database
The CFQUERY in CompanyDeleteAction.cfm uses a DELETE statement with two SQL clauses: DELETE and WHERE. DELETE tells the database the table from which to delete a record, and WHERE tells the database which record to delete. You can watch the company delete process in action. Point your Web browser to http://<yourserver>/CFMXBible/Ch02/CompanyGetDeleteForm.cfm and enter a CompanyID. (To get a valid ID, go to the company list and pick a number from the ID column.) Click Submit to see the chosen company’s informatio...

3. Modifying an Employee in the Database
The DateFormat() function around the DateOfBirth column in the codereturns the employee’s birth date reformatted according to a display mask. DateOfBirth normally comes back from the database in the following format: 2002-01-01 00:00:00.0 That format is not very user-friendly. Calling DateFormat() with a mask of “mm/dd/yyyy” returns the date as follows: 01/01/2002 This version is, of course, more natural and easy to read. The same is true for the employee edit process...

4. Removing an Employee From the Database
The user must have the capability to remove employees from the database. The employee delete process is a simple combination of techniques that you have already learned, such as retrieving a record from the database, displaying that record in a template, and so on. The first page in this process is nearly identical to the employee get edit form. Create a file named EmployeeGetDeleteForm.cfm inside the Ch02 directory, type the code into the file’s editing window, and save the file. <html> <head> <ti...

5. Making direct links to the forms
Say that you want to modify or delete a company. Right now, you need to remember the company’s ID, go back to the launch pad, click Company Edit, and enter the company ID, all just to get to the edit form. Wouldn’t you rather click a company in the list and go directly to the edit form? ... <table> <tr> <td><b>ID</b></td> <td><b>Name</b></td> <td><b>Address</b></td> <td><b>City</b></t...

6. Using a Custom Tag
Custom tags are reusable, developer-authored extensions to the ColdFusion language. The custom tag that you create in the following parts displays today’s date in a familiar format. Create a file named TodaysDate.cfm inside the Ch02 directory, type the code into the file’s editing window, and save the file. <cfoutput>#DateFormat(Now(), “ddd, mmm d, yyyy”)#</cfoutput> Now() returns the current date and time, and DateFormat() reformats the date. To call your custom tag, open index.cfm, a...

7. Creating your physical data model
Physical data models are extracted from their logical counterparts by mapping logical objects to physical objects supported by the target database platform. The following table shows the relationship between logical and physical objects. In many cases, your physical data model almost mirrors your logical data model because entities typically map directly to the tables that store them. Exceptions to this rule are logical data models that contain nonspecific relationships and entity subtypes. Although entity subtypes are an advanced top...

8. Understanding All Relational Result Sets
This article can help you better understand complicated SQL containing multitable joins, group-related clauses, and aggregate functions—by far the most problematic topics for most database developers. You also learn the correct way to handle database exceptions and incorporate them as actual functionality in your ColdFusion application. You learn, too, how to increase performance by caching queries in memory for fast access. You can memorize SQL clauses and Bachus-Naur forms until you’re blue in the face, ...

9. How and when to use Group by Having and Distinct
After learning how SQL works internally, you can better learn how to put the more complicated aspects of it to use. First we need to clarify the difference between GROUP BY and DISTINCT. Quite a bit of confusion exists over these two clauses, because they often produce the same query results but for very different reasons. In fact, GROUP BY and DISTINCT are not related in any way whatsoever. The GROUP BY clause produces as its intermediate work product a table of rows representing each group, and a sort of “invisible third dimen...

10. Query Caching
Query caching places the results of a database query into ColdFusion Server’s memory where it can be instantly retrieved without querying the database. Query caching is one of the most useful tools for enhancing performance in your ColdFusion applications; unfortunately, it is also one of the least used. A few caveats are involved in query caching, but all in all, it is a very straightforward technique to employ. You should consider caching only queries that fit the following criteria: The query has a significant ...