arrays

kjerk edited this page Oct 17, 2013 · 3 revisions

Previous Recordsets --- Next Structures

## 7. Arrays

Often we need to organize a group and put them into a collection. There are two main types of collections: arrays and structures.

An array is a number-indexed list. Picture a city block of houses. Together they form an array and their addresses are the indices. Each house on the block will have a unique address. Some addresses might be empty, but the addresses are all in a specific order. The index is the address of a specific element inside the array. In CFML the index always begins with "1". Say that again, ColdFusion uses 1 based arrays. This is different than some other languages and is very important to note.

An array can be created 2 ways in CFML. Starting with ColdFusion 9 we can use shorthand notation to create an array. We do this as an opening [ then zero or more elements, and a closing ]. Try out this code:

Tag Syntax

<cfset favorite_colors = ["red","blue","green","black","brown"] />
<cfdump var = "#favorite_colors#" /><br />
<cfdump var = "#favorite_colors[2]#" /><br />
<cfdump var = "#ArrayLen(favorite_colors)#" /><br />

Script Syntax

<cfscript>

    favorite_colors = ["red","blue","green","black","brown"];
    writeDump(favorite_colors);
    writeOutput("<br />");
    writeDump(favorite_colors[2]);
    writeOutput("<br />");
    writeDump(var = ArrayLen(favorite_colors));

</cfscript>

Prior to ColdFusion 9 or if you need an array with multiple dimensions (think associative arrays and matrices) we can use the arrayNew() function. ArrayNew() takes a single argument which is the number of dimensions the array has. We can create up to three dimensional arrays in ColdFusion.

Tag Syntax

<cfset myArray = arrayNew(2) />
<cfset myArray[1][1] = 'Hammer' />
<cfset myArray[1][2] = 'Nail' />
<cfset myArray[2][1] = 'Screwdriver' />
<cfset myArray[1][2] = 'Screw' />

Script Syntax

<cfscript>

    myArray = arrayNew(2);
    myArray[1][1] = 'Hammer';
    myArray[1][2] = 'Nail';
    myArray[2][1] = 'Screwdriver';
    myArray[1][2] = 'Screw';

</cfscript>

Keep going with these, but try to understand what each instruction is doing before we explain them:

Tag Syntax

<cfset ArrayAppend(favorite_colors, "orange") />
<cfset favorite_colors[3] = "yellow" />

<cfdump var = "#favorite_colors#" /><br />

<cfset ArraySort(favorite_colors,"text") />
<cfset ArrayDeleteAt(favorite_colors, 2) /> 

<cfdump var = "#favorite_colors#" /><br />

Script Syntax

<cfscript>

    ArrayAppend(favorite_colors, "orange");
    favorite_colors[3] = "yellow";
    
    writeDump(favorite_colors);
    writeOutput("<br />");
    
    ArraySort(favorite_colors,"text");
    ArrayDeleteAt(favorite_colors, 2);
    
    writeDump(var = favorite_colors);
    writeOutput("<br />"); 

</cfscript>

We can also search an array for a specific value and get the index

Tag Syntax

<cfset brownIndex = ArrayFind(favorite_colors,"brown") />
<cfdump var="#brownIndex#" />

Script Syntax

<cfscript>

    brownIndex = ArrayFind(favorite_colors,"brown");
    WriteDump(brownIndex);

</cfscript>

In order to get an element in the array you use the syntax ArrayAppend(array,"value") or arrayname[index] = "value". The first example of adding an array element is with an instruction. The second is updating an array element is by assignment. So looking at the final "favorite_colors" array:

  • What's the index of brown ?
  • What did the "ArraySort" instruction do to the collection?
  • What does "ArrayLen" instruction return?

There are lots of cool things to do with an array. You can rearrange the order of the elements using the ArraySort instruction like we did in the last example. You can iterate through each element using the cfloop instruction. You can find the address of a specific element by using the arrayName[index] instruction. You can ask an array if an element is present with the ArrayIsDefined instruction. Try out this example that brings a bunch of things together:

Tag Syntax

<cfoutput>
<ul>
    <cfloop array = "#favorite_colors#" index = "target" >
        <li>
        #target# is #len(target)# letters long.
        </li>
    </cfloop>
</ul>
</cfoutput>
<cfdump var = "#ArrayIsDefined(favorite_colors,4)#" />

Script Syntax

<cfscript>

    writeOutput ("<ul>");
    
    index = favorite_colors.iterator ();
    while (index.hasNext ()) {
        target = index.next ();
        writeOutput ("<li>#target# is #len(target)# letters long.</li>");
    }
    
    writeOutput ("</ul>"); 
    writeDump (var = ArrayIsDefined (favorite_colors, 4));

</cfscript>

We use arrays whenever we need a list where the elements are in a specific order.

Looping

Just like looping queries, there are multiple ways to loop over arrays.

Array Loop

Starting with Adobe ColdFusion 8 you can loop over an array using <cfloop> by passing the array directly into the <cfloop>'s array attribute. When specifying an array loop, we also have to pass in an index. Inside the loop each individual array value is referenced by the index. This can be confusing as the index is not really an index at all, but rather reference to the value stored within the array at that index.

Tag Syntax

<cfset myArray = ['Alan', 'Bill', 'Matt'] />
<cfoutput>
    <cfloop array="#myArray#" index="arrayValue">
        #arrayValue# <br />
    </cfloop>
</cfoutput>
Output:
Alan
Bill
Matt

One more thing to notice in the example above is that we do not pass in the string name of the array as we did before with the query loop. Instead, we pass in the array value itself. Last thing here, there is no <cfscript> equivalent to an array loop. See below for more ways to loop over an array which include <cfscript> options.

Script Syntax

The same effect can be achieved with a foreach style for x in y loop in script syntax.

<cfscript>

    myArray = ['Alan', 'Bill', 'Matt'];
    
    for(name in myArray)
    {
        writeOutput("#name# <br />");
    }

</cfscript>

Iterative loop (index)

<cfloop> also allows us to iterate over an array as an indexed loop. An indexed loop is used often in <cfscript> where for loops do not support arrays directly. We can start at any index and end at any index. The most common loop starts at 1 and ends at the last element in the array. In an array we can find the total number of elements in an array by using the arrayLen() function. To reference the element by index, use array notation as displayed in the example below.

Tag Syntax

<cfset myArray = ['Alan', 'Bill', 'Matt'] />
<cfoutput>
    <cfloop from="1" to="#arrayLen(myArray)#" index="i">
        #myArray[i]#<br />
    </cfloop>
</cfoutput>
Output:
Alan
Bill
Matt

Script Syntax

<cfscript>

    myArray = ['Alan', 'Bill', 'Matt'];
    
    for (i = 1; i <= arrayLen(myArray); i++ ) {
        writeOutput("#myArray[i]# <br />");
    }

</cfscript>

Previous Recordsets --- Next Structures