arrays and structures - part 1

Understanding Arrays and Structures in ColdFusion
Part 1 of an Ongoing Saga:

Arrays

An array is known as a complex datatype in ColdFusion. Don?t let the term fool you. Complex doesn?t mean they?re hard to understand. Complex only means that they are multidimensional.

What is a multidimensional variable, and why would you want to burden yourself with it? Allow me to explain.

First, let?s take a look at a ?simple? variable?one that you?re more than likely intimately familiar with.

<cfset player = ?John? />

Let?s say John is a player on a baseball team (no, I don?t know which team specifically?pick your favorite and play along).

That was easy enough. We?ve now got a local variable named ?player? with a value of ?John?.

What if we want to store the names of the other eight players on the team?

Sure, we can do:

<cfset player1 = ?John? />
<cfset player2 =
?Bob? />
<cfset player3 =
?Frank? />
<cfset player4 =
?Pete? />
<cfset player5 =
?Hank? />
<cfset player6 =
?Dave? />
<cfset player7 =
?Craig? />
<cfset player8 =
?Bill? />
<cfset player9 =
?Curly Joe? />

...but now we have to worry about maintaining 9 separate variables. If we want to pass the names of the players on the team to another page, we have to manually pass 9 variables (be it in a URL, form fields, sessions, etc). That leaves a lot of room for error.

Not only that?but what if there were more than 9 ?items? that we were concerned with? What if we were tracking the 30 people working in a particular department? Or the 100 items in inventory? Or the 1700 ways that ColdFusion is better than ASP? (ahem?I digress?).

Back to the 9 players. Now, it is possible to do something like:

<cfset players = ?John, Bob, Frank, Pete, Hank, Dave, Craig, Bill, Curly Joe? />

...which will effectively store the 9 values in one variable. ColdFusion even provides various list functions that will help manipulate/extract values from the list variable. However, list manipulation in CF is relatively slow (especially when compared to array manipulation). Especially if the length of the list begins to approach 1700 items!

So how to efficiently manage multiple values such as this? The answer is?of course? (everybody say it together)?. the array.

1 Dimensional Arrays

As I?ve already mentioned, arrays are multidimensional?and we?ll soon discuss that. But arrays can also be 1 dimensional. Let?s take a look at that first.
<cfset arrPlayers = arrayNew(1) />

An array is created with ColdFusion?s arrayNew() function. arrayNew() takes one argument?the dimensions of the array. ColdFusion supports up to a 3 dimensional array. For this example, we?re creating a simple 1 dimensional array. It is not necessary to preface the name of the variable with ?arr?. This is simply a convention that many people use in order to distinguish between various variable types. You can name your array any syntactically valid ColdFusion variable name (e.g. cannot begin with a number, cannot contain special characters or spaces).

To populate the array once it?s been created:

<cfset arrPlayers[1] = ?John? />
<cfset arrPlayers[2] =
?Bob? />
<cfset arrPlayers[3] =
?Frank? />
<cfset arrPlayers[4] =
?Pete? />
<cfset arrPlayers[5] =
?Hank? />
<cfset arrPlayers[6] =
?Dave? />
<cfset arrPlayers[7] =
?Craig? />
<cfset arrPlayers[8] =
?Bill? />
<cfset arrPlayers[9] =
?Curly Joe? />

Arrays use brackets to indicate the position of the element within the array. By setting arrPlayers[1] = ?John?, we?re assigning the value of John to the first array element. This particular array has elements from 1 through 9 (arrPlayers[9]).

Note: If you are familiar with arrays in JavaScript, Java, C++ (to name a few)...you may expect an array to start at position 0. In ColdFusion, arrays begin at position 1.

Using the <cfdump> tag, we can get a good visual representation of our array:



What?s the advantage of using an array, over creating a list? Two things:

1) Array manipulation is quicker/more efficient than list manipulation. This is because lists are position-oriented, while arrays are math-oriented.

That is to say, if we had the list of players, and we wanted to extract the 3rd player (list element), we would use the listGetAt() function:

<cfoutput>#listGetAt(lsPlayers, 3)#</cfoutput>
(notice the name of the variable changed to indicate that it?s a list?not an array)

This will prompt ColdFusion to parse the string (a list, even though it?s made up of multiple items, is still simply one long string), until it arrives at the 3rd position. In a 9 item list, this process will be relatively quick. However, as a list grows, this parsing will take more and more time.

If we wanted to extract the 3rd player from an array?well, we wouldn?t even need to resort to a function:

<cfoutput>#variables.arrPlayers[3]#</cfoutput>

ColdFusion does not have to parse the entire array. It knows exactly where to go (element 3), and goes directly to that element without having to ever touch elements 1 or 2. You can see where this would offer a significant performance increase over lists. Especially in a larger group of data.

2) A list is limited to a one-dimensional string. An array, however, can be multi-dimensional. What if, in addition to the player?s name, we wanted to store the position they play? We are now talking about a 2 dimensional array. This is where people sometimes get intimidated. But in reality, this is nothing more than two 1 dimensional arrays. In reality?it?s a grid. We?ll look at multidimensional arrays next.

2 Dimensional Arrays

If you feel that you have a good understanding of a 1 dimensional array, 2 dimensional arrays should be no problem, as they are simply nested 1 dimensional arrays.

Continuing on with the baseball player array?what if, in addition to the player?s name, we also wanted to keep track of the position that player plays?

<cfset arrPlayers = arrayNew(2) />

Again, we use the arrayNew() function?but this time we pass 2 as an argument, indicating that we want to create a 2 dimensional array.

The code to populate this new array is below, with an explanation following.

<cfset arrPlayers[1][1] = ?John? />
<cfset arrPlayers
[1][2] = ?First Base? />

<cfset arrPlayers
[2][1] = ?Bob? />
<cfset arrPlayers
[2][2] = ?Second Base? />

<cfset arrPlayers
[3][1] = ?Frank? />
<cfset arrPlayers
[3][2] = ?Third Base? />

<cfset arrPlayers
[4][1] = ?Pete? />
<cfset arrPlayers
[4][2] = ?Shortstop? />

<cfset arrPlayers
[5][1] = ?Hank? />
<cfset arrPlayers
[5][2] = ?Left Field? />

<cfset arrPlayers
[6][1] = ?Dave? />
<cfset arrPlayers
[6][2] = ?Center Field? />

<cfset arrPlayers
[7][1] = ?Craig? />
<cfset arrPlayers
[7][2] = ?Right Field? />

<cfset arrPlayers
[8][1] = ?Bill? />
<cfset arrPlayers
[8][2] = ?Pitcher? />

<cfset arrPlayers
[9][1] = ?Curly Joe? />
<cfset arrPlayers
[9][2] = ?Catcher? />

The length of the array is still 9, even though there are now 18 elements. Each position simply has 2 dimensions. I described it as a grid earlier. Here is a visual representation of that grid:

arrPlayers (Array)
 

  1 2 3 4 5 6 7 8 9
1 John Bob Frank Pete Hank Dave Craig Bill Curly Joe
2 First Base Second Base Third Base Shortstop Left Field Center Field Right Field Pitcher Catcher


The numbers on top represent the first dimension. The numbers along the side represent the second dimension. So following that logic, the value of arrPlayers[3][2] is ?Third Base? (go to the number 3 on top, and the number 2 down the left). For any value in our array, arrPlayers[x][y], x is represented by the top row of numbers, and y is represented by the vertical column of numbers.

And a <cfdump> clearly shows us that our 2d array is simply a 1d array comprised of a series of 1d arrays:



I?ve only shown the first 3 positions, but it still clearly illustrates the point that a 2 dimensional array is simply a 1 dimensional array of 1 dimensional arrays.

It is correct to say:

arrPlayers is a 2 dimensional array that has 9 positions
The first dimension holds the ?name? value
The second dimension holds the ?position played? value

We could go even further, and add each player?s age to the array.

<cfset arrPlayers = arrayNew(2) />

<cfset arrPlayers
[1][1] = ?John? />
<cfset arrPlayers
[1][2] = ?First Base? />
<cfset arrPlayers
[1][3] = 30 />

<cfset arrPlayers
[2][1] = ?Bob? />
<cfset arrPlayers
[2][2] = ?Second Base? />
<cfset arrPlayers
[2][3] = 32 />

<cfset arrPlayers
[3][1] = ?Frank? />
<cfset arrPlayers
[3][2] = ?Third Base? />
<cfset arrPlayers
[3][3] = 28 />

<cfset arrPlayers
[4][1] = ?Pete? />
<cfset arrPlayers
[4][2] = ?Shortstop? />
<cfset arrPlayers
[4][3] = 26 />

<cfset arrPlayers
[5][1] = ?Hank? />
<cfset arrPlayers
[5][2] = ?Left Field? />
<cfset arrPlayers
[5][3] = 31 />

<cfset arrPlayers
[6][1] = ?Dave? />
<cfset arrPlayers
[6][2] = ?Center Field? />
<cfset arrPlayers
[6][3] = 33 />

<cfset arrPlayers
[7][1] = ?Craig? />
<cfset arrPlayers
[7][2] = ?Right Field? />
<cfset arrPlayers
[7][3] = 24 />

<cfset arrPlayers
[8][1] = ?Bill? />
<cfset arrPlayers
[8][2] = ?Pitcher? />
<cfset arrPlayers
[8][3] = 22 />

<cfset arrPlayers
[9][1] = ?Curly Joe? />
<cfset arrPlayers
[9][2] = ?Catcher? />
<cfset arrPlayers
[9][3] = 25 />

Very important to note?this is STILL a 2 dimensional array. It might appear at first that there are 3 dimensions. However, notice that we still only have brackets [x][y] for each of the 9 positions. Each position holds 3 elements, as opposed to two. We could add data for the salary of each player?as well as whether or not they bat left or right. Still, a 2 dimensional array?but would now have 5 elements in each position.

A visualization of the code above might be in order:

variables.arrPlayers (Array)

  1 2 3 4 5 6 7 8 9
1 John Bob Frank Pete Hank Dave Craig Bill Curly Joe
2 First Base Second Base Third Base Shortstop Left Field Center Field Right Field Pitcher Catcher
3 30 22 28 26 31 33 24 22 25

?and a <cfdump> to illustrate it one more way (still only displaying positions 1-3):

So if we want to know the age of the 8th player, we output variables.arrPlayers[8][3]. The position played by the 4th player? variables.arrPlayers[4][2].

Obviously, this wouldn?t be possible with a list. And we have effectively stored 27 separate, unique values in one single variable.

That?s really the basics behind an array, which is what I wanted to demonstrate. Anything more would push this tutorial out of the beginner?s area, where I would prefer to keep it. Arrays (and Structures?see part 2 of this tutorial ?series?) were a difficult concept for me to grasp coming into ColdFusion with no prior programming experience. I hope that the description above will make it easier for others in the same situation.

A couple of final thoughts?

Although I only described 1 dimensional and 2 dimensional arrays, ColdFusion supports up to 3 dimensions. If a 2 dimensional array can be represented by a grid (as I?ve shown above), then a 3 dimensional array can be represented by a cube.

ColdFusion arrays are dynamic. This means if you have a 9 position array (for the sake of simplicity, let?s consider our original 1 dimensional array, that held the names of the players on the team)?and you remove the element at position 4, you now have an 8 element array (all elements that followed 4 slide ?up? one position). Some other languages would leave a NULL value at position 4, and maintain a 9 position array. So this distinction between ColdFusion arrays and array behaviour in other languages is important to remember.

How would we remove the element at position 4? We would use the arrayDeleteAt() function. All of ColdFusion?s built-in array functions can be found in your online documentation, or at http://livedocs.macromedia.com/coldfusion/6/CFML_Reference/functions-pt06.htm#3473387

If you feel that you?ve got a fundamental understanding of arrays, please check out Part 2 of this series, which covers Structures.

As always, if there are any questions or any areas that I can clarify for you, please don?t hesitate to contact me directly, or via the easycfm.com forums (preferably the latter, so that others might benefit from the discussion).



All ColdFusion Tutorials By Author: Charlie Griefer (CJ)
  • arrays and structures - part 1
    part one of a three-part tutorial designed to gently introduce you to the world of complex variables.
    Author: Charlie Griefer (CJ)
    Views: 22,030
    Posted Date: Monday, August 11, 2003
  • arrays and structures - part 2
    part two of a three-part tutorial designed to gently introduce you to the world of complex variables.
    Author: Charlie Griefer (CJ)
    Views: 14,949
    Posted Date: Monday, August 11, 2003
  • arrays and structures - part 3
    part three of a three-part tutorial designed to gently introduce you to the world of complex variables.
    Author: Charlie Griefer (CJ)
    Views: 17,018
    Posted Date: Monday, August 11, 2003
  • CF 'Best Practices'
    Some tips and techniques that I've picked up over the years. I don't maintain that these are 'official' or 'absolute'...they are simply my preference and things that have worked for me. I would like to share them here, and leave you to make the decision as to whether or not they fit in your 'code arsenal' :)
    Author: Charlie Griefer (CJ)
    Views: 20,825
    Posted Date: Friday, August 15, 2003
  • CFSCRIPT Intro
    An introductory look at CFSCRIPT. Rules, some basic syntax, and a couple of examples of loops and conditional processing.
    Author: Charlie Griefer (CJ)
    Views: 26,315
    Posted Date: Saturday, January 18, 2003
  • ColdFusion Mad Libs - Part I
    A silly but fun time-waster that you can easily include on your Web site. You might be surprised at how addicting it can become :)
    Author: Charlie Griefer (CJ)
    Views: 16,547
    Posted Date: Thursday, May 29, 2003
  • ColdFusion Mad Libs - Part II
    You've finished the first Mad Libs tutorial, but you feel like there's something missing. Of course there is! You want to be able to save the final output to a database to let your visitors browse through other user's stories. Includes a bad-words filter for the more conservative among us :)
    Author: Charlie Griefer (CJ)
    Views: 13,281
    Posted Date: Thursday, May 29, 2003
  • Dynamic Column Output (Part One)
    Have you ever wanted to display your content in rows of 3 columns? If you ever wanted to specify the number of columns per row within your content, here's the tutorial for you.
    Author: Charlie Griefer (CJ)
    Views: 19,444
    Posted Date: Thursday, May 29, 2003
  • Dynamic Column Output (Part Two)
    This tutorial picks up where the Dynamic Columns tutorial left off, showing you how to not only output your data in a specified number of columns, but how to do it while still publishing well formed HTML.
    Author: Charlie Griefer (CJ)
    Views: 14,896
    Posted Date: Saturday, May 31, 2003
  • Grouping Output in CF
    How to group cfquery output in order to effectively display relational database data. Includes an overview of how to output nested groups as well.
    Author: Charlie Griefer (CJ)
    Views: 17,515
    Posted Date: Tuesday, June 17, 2003
  • Helping users obtain their passwords
    Your site requires your visitors to log in. of course, some of your visitors are going to forget their passwords (ok, most will forget their passwords). You don't want them to have to send you an e-mail, and then wait for a response. They need immediate access.

    This tutorial shows two methods by which you can accomodate them.
    Author: Charlie Griefer (CJ)
    Views: 15,959
    Posted Date: Thursday, August 28, 2003
  • JavaScript Form Validation
    Yes, I know we're a ColdFusion site...but ColdFusion does not live in a vacuum. We have to know SQL, HTML, CSS...and sometimes...JavaScript! This tutorial focuses on using JavaScript (in lieu of cfform) to create client side form validation (and explains why writing your own is better than using ).
    Author: Charlie Griefer (CJ)
    Views: 33,495
    Posted Date: Thursday, August 14, 2003
  • Remote File Management
    Manage text-based files on your server from any Web browser. Create a new file, edit a file, or delete a file. Can be a life saver if you're on the road, and find an error in some of your code that needs a quick fix.
    Author: Charlie Griefer (CJ)
    Views: 16,506
    Posted Date: Tuesday, June 3, 2003
  • Save your visitor's clickstreams
    A nifty little custom tag that will allow you to save a visitor's clickstream through your site, as well as display it back to them (with links). Did I really just say 'nifty'?
    Author: Charlie Griefer (CJ)
    Views: 14,161
    Posted Date: Monday, June 16, 2003
  • to cfqueryparam or not to cfqueryparam
    It's been out there since ColdFusion 4.5...most of us have heard of it...few of us use it. Here are some compelling reasons why you should get into the habit of using the tag.
    Author: Charlie Griefer (CJ)
    Views: 19,681
    Posted Date: Thursday, May 29, 2003