arrays and structures - part 3

Understanding Arrays and Structures in ColdFusion

Part 3 of an Ongoing Saga:

(if you have not yet read parts 1 and 2 of this tutorial, I strongly urge you to do so prior to reading this final chapter).

If you?ve made it this far, congratulations! You know what an array is, and you know what a structure is. You can create a 1d or 2d array, and you can create a structure and nested structures.

This final chapter will show you how to actually use arrays and structures?and how to use the two together in order to overcome the limitations of each.

If you?ve been with us through parts 1 and 2 of this tutorial, you remember that we were using the players on a baseball team to illustrate arrays and structures.

The array looked like (shortened for brevity):

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

The problem was accessing the age of the second baseman required somewhat cryptic code:

<cfoutput>#arrPlayers[2][3]#</cfoutput>


We then delved into structures. A structure holding player info looked like:

<cfset stPlayer = structNew() />

<cfset stPlayer.position =
?First Base? />
<cfset stPlayer .age =
30 />
<cfset stPlayer.salary =
200,000 />
<cfset stPlayer.bats =
?right? />

This allowed us to use code that was easy to understand in outputting values:

<cfoutput>#stPlayer.age#</cfoutput>

Very intuitive?but we can only create one structure per player. How can we create one single variable that will hold information about all members of the team?

An array of structures.

We will create a 1 dimensional array, called arrPlayers. We did this waaaay back in the first part of this tutorial, so it should be cake for you now.

<cfset arrPlayers = arrayNew(1) />

In the first array position, we want to store all of the information about our first baseman, John. As we saw in the previous chapter, the best way to do this is with a structure. So in position 1, we create a structure:

<cfset arrPlayers[1] = structNew() />

And to populate that structure:

<cfset arrPlayers[1].playerName = ?John? />
<cfset arrPlayers[1].position =
?First Base? />
<cfset arrPlayers[1].age =
?30? />

Before we go any further, let?s take a look at what we?ve just created:



You can see the array (indicated in a <cfdump> by a green table), which contains a structure (indicated in a <cfdump> by a blue table).

So?<cfoutput>#arrPlayers[1].playerName#</cfoutput> gives us an output of John. Again, much more straightforward than storing all of the information in an array. Plus, we can now add more players:

<cfset arrPlayers[2] = structNew() /> // creates an empty struct

<cfset arrPlayers[2].playerName = ?Bob? /> // populates the player?s name
<cfset arrPlayers
[2].position = ?Second Base? /> // populates the player?s position
<cfset arrPlayers
[2].age = ?32? /> // populates the player?s age

We?ve now created a second position in our 1 dimensional array. We populated it with a new structure, and then populated the structure with the relevant information. We simply continue to do this for each player on the team, and ultimately we end up with:



This variable, even though it is a series of nested complex variables, is still one single variable. Furthermore, we can easily get at the information we want.

<cfoutput>#arrPlayers[4].age#</cfoutput> is clearly going to return 26.

In fact, let?s output all of the player information. An array without a loop is like a car without an engine. You?ll find that as you use arrays more and more, you?ll most frequently be looping over them.

1. <cfoutput>
2. <table border="1">
3.  <tr>
4.    <td style="font-weight:bold;">Player Name&nbsp;&nbsp;</td>
5.    <td style="font-weight:bold;">Position&nbsp;&nbsp;</td>
6.    <td style="font-weight:bold;">Age</td>
7.  </tr>
8.  <cfloop from="1" to="#arrayLen(arrPlayers)#" index="i">
9.  <tr>
10.   <td>#arrPlayers[i].playerName#</td>
11.   <td>#arrPlayers[i].position#</td>
12.   <td style="text-align:right;">#arrPlayers[i].age#</td>
13. </tr>
14. </cfloop>
15. </table>
16. </cfoutput>

Obligatory line-by-line breakdown:

1. Open a <cfoutput> tag. I frequently see people put their <cfoutput></cfoutput> inside of a <cfloop>. It?s much better to place the <cfoutput>?s outside of the loop. This way the tag is only called once, rather than once for each iteration of the loop.
2. Create an HTML table
3. Create a new table row
4. A column heading (Player)
5. A column heading (Position)
6. A column heading (Age)
7. Ending a table row
8. Our loop. We use the ColdFusion function arrayLen() to determine the number of times we will loop. In this instance, #arrayLen(arrPlayers)# will evaluate to 9, as we have 9 array positions.
9. Create a new table row for each iteration of the loop.
10. Output each player?s name in a table cell. #arrPlayers[i].playerName# will accomplish this. Bear in mind that the value of i will increment with each iteration of the loop.
11. Output each player?s position in a table cell.
12. Output each player?s age in a table cell.
13. Close the table row for each iteration of the loop.
14. End loop
15. Close table
16. Close <cfoutput>

And when we view this in a browser, we see:



Another example of a practical use of arrays and structures is a shopping cart.

This is not meant to be a full-fledged shopping cart tutorial, so I will be explaining just enough to demonstrate the array/structure aspect.

Assume a session variable called session.shoppingCart. session.shoppingCart is initialized as a new array (this would be done within your Application.cfm template). If you?re not familiar with session variables at this point, that?s ok. For the purposes of this demonstration, simply realize that a session variable is persistent?it can be accessed from any page within an application.

Each client will start off with their own instance of session.shoppingCart?an empty array.

<cfdump var=?#session.shoppingCart#?>


Assume each product has a product ID, a color, a size, and a price.

For each item that the client places into the cart:

1. <cfset temp = arrayAppend(session.shoppingCart, structNew())>

2. <cfset session.shoppingcart[arrayLen(session.shoppingcart)].productID = 52>
3. <cfset session.shoppingcart[arrayLen(session.shoppingcart)].color = "red">
4. <cfset session.shoppingcart[arrayLen(session.shoppingcart)].size = "XXL">
5. <cfset session.shoppingcart[arrayLen(session.shoppingcart)].quantity = 2>


1. First, we create a new structure to hold the information for the item that the user is placing in the cart. We do this with an arrayAppend() function. arrayAppend() will add a new position at the end of a given array. It returns TRUE or FALSE, which is why we use a temp variable.

If we have 3 items in the cart, arrayAppend(session.shoppingCart, structNew()) will create a 4th array position and populate it with an empty structure.

2. Because we don?t necessarily know what position we?re going to be inserting the new item into, we do not reference array positions using session.shoppingcart[4]. Instead, we use the arrayLen() function to create a more dynamic method. arrayLen() returns the length of the array?which will always point to the last position (which is where we?re inserting the new item into the cart). In lines 2 ? 5, we populate the structure that we just created in the last array position with productID, color, size, and quantity.

<cfdump var=?#session.shoppingCart#?>


Now, let?s say the user adds another item. We would re-use the same code, inserting the appropriate values. Assume the user has 3 products in the cart.

<cfdump var=?#session.shoppingCart#?>


Want to know how many items are in the cart at any given time? Simply loop over the array, and add the quantity values together:

<cfset totalItems = 0>
<cfloop from=
"1" to="#arrayLen(session.shoppingcart)#" index="i">
   <cfset totalItems = variables.totalItems + session.shoppingcart[
i].quantity>
</cfloop>


You have: <cfoutput><strong>#variables.totalItems#</strong></cfoutput> items in your cart

Let?s say the customer decides that green isn?t his (or her) color. They want to remove the 2nd item from their cart.

<cfset temp = arrayDeleteAt(session.shoppingcart, 2)>

Because the ColdFusion function arrayDeleteAt() returns TRUE or FALSE, we must use a temp variable. Beyond that, the function requires 2 arguments. The array to be manipulated, and the position to remove.

Running the arrayDeleteAt() function leaves us with:



What is important to note here is that by removing position 2, everything after position 2 shifts up. What was an array with a length of 3 is now an array with a length of 2.

Some languages would have left the array with 3 positions, and a null value at position 2. Because ColdFusion arrays are dynamic in nature, they will shrink to accommodate the removal of an element.


Final Thoughts

I urge you to familiarize yourself with ColdFusion?s built in array functions and structure functions. If you installed the ColdFusion documentation during your CF install, everything you need is on your server (by default, located at http://localhost/cfdocs/).

I realize that there are likely still quite a few questions. Arrays and structures, while not really difficult subjects, do represent the ?next level? of understanding not only ColdFusion, but programming concepts in general. I?ve tried to keep these tutorials as simple as possible?yet as comprehensive as possible, without turning them into advanced level tutorials.

I don?t expect you to feel that you?re ready to sit down and write a shopping cart application in the next 20 minutes. I *do* expect that you have a general understanding of an array and a structure?and how to use both (individually and together). I expect that you will build on this foundation by experimenting with your own code, as well as posting questions to the forums, or e-mailing me when you?re stuck.

If there are lingering questions?ask. If you feel another tutorial (perhaps more intermediate to advanced level) is warranted?suggest it.

I look forward to hearing from you.

CJ

All ColdFusion Tutorials By Author: Charlie Griefer (CJ)
  • 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: 46,873
    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: 27,666
    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: 22,839
    Posted Date: Thursday, May 29, 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: 34,135
    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: 34,987
    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: 27,534
    Posted Date: Saturday, May 31, 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: 27,815
    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: 25,608
    Posted Date: Monday, June 16, 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: 32,508
    Posted Date: Tuesday, June 17, 2003
  • 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: 38,749
    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: 28,290
    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: 33,333
    Posted Date: Monday, August 11, 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: 58,283
    Posted Date: Thursday, August 14, 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: 35,637
    Posted Date: Friday, August 15, 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: 26,198
    Posted Date: Thursday, August 28, 2003
Download the EasyCFM.COM Browser Toolbar!