Creating and using structures

This section explains how to create and use structures in ColdFusion. The sample code in this section uses a structure called employee, which is used to add new employees to a corporate information system.

Creating structures

You can create a structure by creating a first key-pair or by using the ColdFusion StructNew function.

Creating structures by assigning values

You can create a structure by assigning a key-value pair. For example, the following line creates a structure named myStruct with one element, name, that has the value Macromedia.

<cfset myStruct.name="Macromedia">

Creating structures using a function

You can create structures by assigning a variable name to the structure with the StructNew function as follows:

<cfset mystructure=StructNew()>

For example, to create a structure named departments, use the following syntax:

<cfset departments=StructNew()>

This creates an empty structure to which you can add data.

Use this technique to create structures if your application must run on ColdFusion Server versions 5 and earlier.

Adding data elements to structures

You add an element to a structure by assigning the element a value or by using a ColdFusion function. It is cleaner and more efficient to use direct assignment, so only this technique is described.

You add structure key-value pairs by defining the value of the structure key, as shown in the following example:

<cfset myNewStructure.key1="A new structure with a new key">
<cfdump var=#myNewStructure#>
<cfset myNewStructure.key2="Now I've added a second key">
<cfdump var=#myNewStructure#>

Updating values in structures

You can update structure element values by assignment or by using the StructUpdate function. Direct assignment results in simpler code than using a function, so only the assignment technique is described.

To update a structure value, assign the key a new value. For example, the following code uses cfset and object.property notation to create a new structure element called departments.John, and changes John's department from Sales to Marketing. It then uses associative array notation to change his department to Facilities. Each time the department changes, it displays the results:

<cfset departments=structnew()>
<cfset departments.John = "Sales">
<cfoutput>
  Before the first change, John was in the #departments.John# Department<br>
</cfoutput>
<cfset Departments.John = "Marketing">
<cfoutput>
  After the first change, John is in the #departments.John# Department<br>
</cfoutput>
<cfset Departments["John"] = "Facilities">
<cfoutput>
  After the second change, John is in the #departments.John# Department<br>
</cfoutput>

Getting information about structures and keys

The following sections describe how to use ColdFusion functions to find information about structures and their keys.

Getting information about structures

To find out if a given value represents a structure, use the IsStruct function, as follows:

IsStruct(variable)

This function returns True if variable is a ColdFusion structure. (It also returns True if variable is a Java object that implements the java.util.Map interface.)

Structures are not indexed numerically, so to find out how many name-value pairs exist in a structure, use the StructCount function, as in the following example:

StructCount(employee)

To discover whether a specific Structure contains data, use the StructIsEmpty function, as follows:

StructIsEmpty(structure_name)

This function returns True if the structure is empty, and False if it contains data.

Finding a specific key and its value

To determine whether a specific key exists in a structure, use the StructKeyExists function, as follows:

StructKeyExists(structure_name, "key_name")

Do not put the name of the structure in quotation marks, but you do put the key name in quotation marks. For example, the following code displays the value of the MyStruct.MyKey only if it exists:

<cfif StructKeyExists(myStruct, "myKey")>
<cfoutput> #mystruct.myKey#</cfoutput><br>
</cfif>

You can use the StructKeyExists function to dynamically test for keys by using a variable to represent the key name. In this case, you do not put the variable in quotes. For example, the following code loops through the records of the GetEmployees query and tests the myStruct structure for a key that matches the query's LastName field. If ColdFusion finds a matching key, it displays the Last Name from the query and the corresponding entry in the structure.

<cfloop query="GetEmployees">
<cfif StructKeyExists(myStruct, LastName)>
<cfoutput>#LastName#: #mystruct[LastName]#</cfoutput><br>
</cfif>
</cfloop>

If the name of the key is known in advance, you can also use the ColdFusion IsDefined function, as follows:

IsDefined("structure_name.key")>

However, if the key is dynamic, or contains special characters, you must use the StructKeyExists function.

Note:   Using StructKeyExists to test for the existence of a structure entry is more efficient than using IsDefined. ColdFusion scopes are available as structures and you can improve efficiency by using StructKeyExists to test for the existence of variables.

Getting a list of keys in a structure

To get a list of the keys in a CFML structure, you use the StructKeyList function, as follows:

<cfset temp=StructKeyList(structure_name, [delimiter] )>

You can specify any character as the delimiter; the default is a comma.

Use the StructKeyArray function to returns an array of keys in a structure, as follows:

<cfset temp=StructKeyArray(structure_name)>

Note:   The StructKeyList and StructKeyArray functions do not return keys in any particular order. Use the ListSort or ArraySort functions to sort the results.

Copying structures

ColdFusion provides several ways to copy structures and create structure references. The following table lists these methods and describes their uses:
Technique
Use
Duplicate function
Makes a complete copy of the structure. All data is copied from the original structure to the new structure, including the contents of structures, queries, and other objects. As a result changes to one copy of the structure have no effect on the other structure.
This function is useful when you want to move a structure completely into a new scope. In particular, if a structure is created in a scope that requires locking (for example, Application), you can duplicate it into a scope that does not require locking (for example, Request), and then delete it in the scope that requires locking
StructCopy function
Makes a shallow copy of a structure. It creates a new structure and copies all simple variable and array values at the top level of the original structure to the new structure. However, it does not make copies of any structures, queries, or other objects that the original structure contains, or of any data inside these objects. Instead, it creates a reference in the new structure to the objects in the original structure. As a result, any change to these objects in one structure also changes the corresponding objects in the copied structure.
The Duplicate replaces this function for most, if not all, purposes.
Variable assignment
Creates an additional reference, or alias, to the structure. Any change to the data using one variable name changes the structure that you access using the other variable name.
This technique is useful when you want to add a local variable to another scope or otherwise change a variable's scope without deleting the variable from the original scope.

The following example shows the different effects of copying, duplicating, and assigning structure variables:

Create a new structure<br>
<cfset myNewStructure=StructNew()>
<cfset myNewStructure.key1="1">
<cfset myNewStructure.key2="2">
<cfset myArray=ArrayNew(1)>
<cfset myArray[1]="3">
<cfset myArray[2]="4">
<cfset myNewStructure.key3=myArray>
<cfset myNewStructure2=StructNew()>
<cfset myNewStructure2.Struct2key1="5">
<cfset myNewStructure2.Struct2key2="6">
<cfset myNewStructure.key4=myNewStructure2>
<cfdump var=#myNewStructure#><br>
<br>
A StructCopy copied structure<br>
<cfset CopiedStruct=StructCopy(myNewStructure)>
<cfdump var=#CopiedStruct#><br>
<br>
A Duplicated structure<br>
<cfset dupStruct=Duplicate(myNewStructure)>
<cfdump var=#dupStruct#><br>
<br>
A new reference to a structure<br>
<cfset structRef=myNewStructure>
<cfdump var=#structRef#><br>

<br>
Change a string, array element, and structure value in the StructCopy copy.<br>
<br>
<cfset CopiedStruct.key1="1A">
<cfset CopiedStruct.key3[2]="4A">
<cfset CopiedStruct.key4.Struct2key2="6A">
Original structure<br>
<cfdump var=#myNewStructure#><br>
Copied structure<br>
<cfdump var=#CopiedStruct#><br>
Duplicated structure<br>
<cfdump var=#DupStruct#><br>
Structure reference
<cfdump var=#structRef#><br>
<br>
Change a string, array element, and structure value in the Duplicate<br>
<br>
<cfset DupStruct.key1="1B">
<cfset DupStruct.key3[2]="4B">
<cfset DupStruct.key4.Struct2key2="6B">
Original structure<br>
<cfdump var=#myNewStructure#><br>
Copied structure<br>
<cfdump var=#CopiedStruct#><br>
Duplicated structure<br>
<cfdump var=#DupStruct#><br>
Structure reference
<cfdump var=#structRef#><br>
<br>
Change a string, array element, and structure value in the reference<br>
<br>
<cfset structRef.key1="1C">
<cfset structRef.key3[2]="4C">
<cfset structRef.key4.Struct2key2="6C">
Original structure<br>
<cfdump var=#myNewStructure#><br>
Copied structure<br>
<cfdump var=#CopiedStruct#><br>
Duplicated structure<br>
<cfdump var=#DupStruct#><br>
Structure reference
<cfdump var=#structRef#><br>
<br>
Clear the original structure<br>
<cfset foo=structclear(myNewStructure)>
Original structure:<br>
<cfdump var=#myNewStructure#><br>
Copied structure<br>
<cfdump var=#CopiedStruct#><br>
Duplicated structure<br>
<cfdump var=#DupStruct#><br>
Structure reference:<br>
<cfdump var=#structRef#><br>

Deleting structure elements and structures

To delete a key and its value from a structure, use the StructDelete function, as follows:

StructDelete(structure_name, key [, indicateNotExisting ])

The indicateNotExisting argument tells the function what to do if the specified key does not exist. By default, the function always returns True. However, if you specify True for the indicateNotExisting argument, the function returns True if the key exists and False if it does not.

You can also use the StructClear function to delete all the data in a structure but keep the structure instance itself, as follows:

StructClear(structure_name)

If you use StructClear to delete a structure that you have copied using the StructCopy function, the specified structure is deleted, but the copy is unaffected.

If you use StructClear to delete a structure that has a multiple references, the function deletes the contents of the structure and all references point to the empty structure, as shown in the following example:

<cfset myStruct.Key1="Macromedia">
Structure before StructClear<br>
<cfdump var="#myStruct#">
<cfset myCopy=myStruct>
<cfset StructClear(myCopy)>
After Clear:<br>
myStruct: <cfdump var="#myStruct#"><br>
myCopy: <cfdump var="#myCopy#">

Looping through structures

You can loop through a structure to output its contents, as shown in the following example:

<!--- Create a structure and set its contents --->
<cfset departments=structnew()>

<cfset val=StructInsert(departments, "John", "Sales")>
<cfset val=StructInsert(departments, "Tom", "Finance")>
<cfset val=StructInsert(departments, "Mike", "Education")>

<!--- Build a table to display the contents --->
<cfoutput>
<table cellpadding="2" cellspacing="2">
  <tr>
    <td><b>Employee</b></td>
    <td><b>Department</b></td>
  </tr>
  <!--- Use cfloop to loop through the departments structure. 
  The item attribute specifies a name for the structure key. --->
  <cfloop collection=#departments# item="person">
    <tr>
      <td>#person#</td>
      <td>#Departments[person]#</td>
    </tr>
  </cfloop>
</table>
</cfoutput>

Comments