Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
I am the chief technical officer at InVision App, Inc - a prototyping and collaboration platform for designers, built by designers. I also rock out in JavaScript and ColdFusion 24x7.
Meanwhile on Twitter
Loading latest tweet...
Ben Nadel at the jQuery Conference 2010 (Boston, MA) with:

Learning ColdFusion 9: Delete Array Elements With ArrayDelete()

By Ben Nadel on
Tags: ColdFusion

A little while ago, I blogged about ColdFusion 9's new ArrayFind() and ArrayContains() methods. ColdFusion 9 also has a similar method for deleting elements from an array: ArrayDelete(). Like ArrayFind() and ArrayContains(), ArrayDelete() takes an array and a target value to delete (rather than a target index as is used in ArrayDeleteAt()). To explore this, I set up a simple demo:

  • <!--- Create an array with simple values. --->
  • <cfset girls = [
  • "Sarah",
  • "Molly",
  • "Sarah",
  • "Joanna",
  • "Carolyn",
  • "Sarah"
  • ] />
  •  
  • <!--- Delete "Sarah" from the array. --->
  • <cfset arrayDelete( girls, "Sarah" ) />
  •  
  • <!--- Output the resultant array. --->
  • <cfdump
  • var="#girls#"
  • label="Girls (minus Sarah)"
  • />

Here, we are building an array of values and then deleting one of them. Notice that the value that we are deleting, "Sarah," appears multiple times within the original array. After we call ArrayDelete() on the array with the target value, "Sarah," we get the following CFDump output:

 
 
 
 
 
 
ColdFusion 9's New ArrayDelete() Function Lets You Delete A Given Value From An Array Without Knowing Its Index. 
 
 
 

Notice that only one of the three instances of "Sarah" were removed from the array. As it turns out, ArrayDelete() only deletes the first instance that it finds, leaving the last two intact.

Since both ArrayFind() and ArrayContains() work with complex values, I assumed that ArrayDelete() would as well; but, rather than assuming now and being wrong later, I figured I should run at least one test with complex data:

  • <!--- Create an array with complex values. --->
  • <cfset girls = [
  • {
  • name = "Sarah",
  • isHot = true
  • },
  • {
  • name = "Carolyn",
  • isHot = true
  • },
  • {
  • name = "Sarah",
  • isHot = true
  • }
  • ] />
  •  
  • <!--- Delete "Sarah" from the array. --->
  • <cfset arrayDelete(
  • girls,
  • {
  • name = "Sarah",
  • isHot = true
  • }
  • ) />
  •  
  • <!--- Output the resultant array. --->
  • <cfdump
  • var="#girls#"
  • label="Girls (minus Sarah)"
  • />

Here, you can see rather than having simple girl names, I am creating complex girl objects. And, rather than passing in a simple name to the ArrayDelete() function, I am passing in a struct. When we run this code, we get the expected CFDump output:

 
 
 
 
 
 
ColdFusion 9's new ArrayDelete() Method Also Works With Complex Values As Well As Simple Values. 
 
 
 

Just as we would expect based on the first example, only the first instance of the Sarah girl object was deleted.

But what do we do if we want to delete all of the instances of a given value from our array? One option would be use ColdFusion 9's new ArrayFind() and ArrayDelete() methods in a conditional loop:

  • <!--- Create an array with simple values. --->
  • <cfset girls = [
  • "Sarah",
  • "Molly",
  • "Sarah",
  • "Joanna",
  • "Carolyn",
  • "Sarah"
  • ] />
  •  
  • <!---
  • Keep deleting from the array until no matching
  • values can be found.
  • --->
  • <cfloop condition="arrayFind( girls, 'Sarah' )">
  •  
  • <!--- Delete the given value. --->
  • <cfset arrayDelete( girls, "Sarah" ) />
  •  
  • </cfloop>
  •  
  • <!--- Output the resultant array. --->
  • <cfdump
  • var="#girls#"
  • label="Girls (ArrayFind() Condition)"
  • />

As you can see in the code, we keep looping while ArrayFind() returns a non-zero index. For every instance that ArrayFind() locates, we are then deleting it with ArrayDelete(). And, when we run this code, we get the following CFDump output:

 
 
 
 
 
 
Using CFLoop And A Condition, We Can Delete All Values With ArrayDelete(). 
 
 
 

This time, all three instances of "Sarah" were successfully removed from our girls array.

The above conditional CFLoop works, but it has a fundamental performance flaw: it searches the array twice as many times as it really needs to. The ArrayFind() method in the Condition searches the array to locate the given value; then, within loop body, the ArrayDelete() method searches the array to find the target value again (in order to delete it). Ideally, what we really want to do is capture the index returned by ArrayFind() and use it to delete the specific value within the array:

  • <!--- Create an array with simple values. --->
  • <cfset girls = [
  • "Sarah",
  • "Molly",
  • "Sarah",
  • "Joanna",
  • "Carolyn",
  • "Sarah"
  • ] />
  •  
  • <!---
  • Keep deleting from the array until no matching
  • values can be found. This time, however, rather than
  • using ArrayDelete() to search / delete the given
  • record, we are going to store the match of the target
  • element returned from ArrayFind() and then delete it
  • exactly using ArrayDeleteAt().
  • --->
  • <cfloop condition="targetIndex = arrayFind( girls, 'Sarah' )">
  •  
  • <!--- Delete the specific value. --->
  • <cfset arrayDeleteAt( girls, targetIndex ) />
  •  
  • </cfloop>
  •  
  • <!--- Output the resultant array. --->
  • <cfdump
  • var="#girls#"
  • label="Girls (ArrayDeleteAt())"
  • />

With this new code, we are only searching the array once with ArrayFind() and then deleting the target index with the old-school method, ArrayDeleteAt(). And, when we run this code, we get the same result with hypothetically better performance:

 
 
 
 
 
 
ArrayDeleteAt() Will Give Us Better Performance Than ArrayDelete() If We Are Deleting Multiple Instances Of A Value. 
 
 
 

ArrayDelete() is one of the many minor but excellent updates that ColdFusion 9 brings to the table. However, it seems that this new function will be most useful when deleting a single value from a known array; once you have to delete more than the first instance of a value, you're going to get better performance if you fall back on the older method, ArrayDeleteAt(), which won't require a re-searching of the array.




Reader Comments

The repeated calls to arrayFind() in the last example mean that it's going to start from the beginning to search each time. But, at least, you aren't doing it twice for each iteration, as you would be if you used arrayDelete(), too.

Even that last solution falls short of manually looping over the array and inspecting each value once. (Just remember to do it in reverse.)

So ... yeah. I fail to see the real-world utility of the arrayDelete() function.

@Rick,

Ahh, very true - looping over it backwards and deleting would be the best of all possible worlds. Agreed though, unless you are deleting a single value, I find this to be less usable.

It seems like ArrayDelete() should have an optional 3rd argument for selecting whether you want to remove all instances or only the first (like the removeXXX() functions have.)

This does the same thing in removing duplicates correct? The only limitation is working with one-dim arrays.

hashSet = CreateObject("java","java.util.LinkedHashSet").init(girls);
girl s= hashSet.toArray();

If arraydelete() is faster for two-dim arrays, that is where I would find it most useful. It beats nested loops.

arrayDelete(myArray, "Sarah") functionality has been available since the Java conversion via myArray.remove("Sarah"). And be careful with the array->Set->array conversion - that removes any ordering in the array.

If you care about ordering you'll need to use the Set manually (in psuedo-code):

s = new java.util.HashSet();
for (i = arrayLen(myArray); i >= 1; i -= 1) {
if (NOT s.add(myArray[i])) {
// it was already in there, so delete it
arrayDeleteAt(myArray, i);
}
}

ArrayDelete returns a boolean value specifying whether the deletion was successful. It will return false if and only if the element was not found. So you can run ArrayDelete in a loop until the method returns false. That way you don't need to do a find and then delete in a loop.

nice demo! man what is with ur obsession with girls! every demo has smthing to do with the ladies, not that i mind....

I'm disappointed in the example
girls-is hot
rather insulting.. to us women..
but thanks for the tech info

:(