How dot notation automatically creates a nested structure

an article added by: Amanda Baker at 04022008


Programming :: How dot notation automatically creates a nested structure ::

 French | Spanish | Portuguese | Italian | German | Japanese | Chinese | Korean | Russian | Arabic Bookmark and Share

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. First ColdFusion Application
You learn by doing, and then we go back and explain how ColdFusion worked its magic. Before you get started, though, you must learn a few terms, set up the database, and create the Web directory that you’re going to use. These are some terms that you should know: A template is a file with a .cfm extension. ColdFusion executes these templates and produces HTML that is returned to the user’s browser. A page is what appears in your browser. It is rendered from the HTML that ColdFusion Server sends back ...

2. Building the company add action template
In this article, you create the template that puts your form data into the database. Create a file named CompanyAddAction.cfm inside the Ch02 directory, type the code into the file’s editing window, and save the file. <cfquery name=”InsertCompany” datasource=”#Request.MainDSN#”> INSERT INTO Company( CompanyName, Address, City, State, ZipCode, Comments ) VALUES ( ‘#Trim(Form.CompanyName)#’, ‘#Trim(Form.Address)#’, ...

3. Modifying a Company in the Database
The data that CFQUERY requests from the database comes back in a result set, and the Name attribute tells ColdFusion what that result set is to be named. The SQL statement consists of three clauses: SELECT, FROM, and ORDER BY. SELECT tells the database which columns to retrieve from the database; FROM tells the database which table to retrieve those columns from; and ORDER BY tells the database how to sort the results. The result set returned from CFQUERY contains multiple rows of data, and each row has multiple columns. It would ...

4. 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)...

5. 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...

6. 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...

7. 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...

8. 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...

9. 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...

10. 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...