views:

891

answers:

4

I have a semi-large (hundreds of records) 1-dimensional array in Coldfusion. Each item in the array is a struct with several properties. I want to search the array for a struct that has a specific "name" property. I know that for an array of string values I could use Java methods like so:

<cfset arrayIndex = myArray.indexOf("WhatImLookingFor") + 1>

...but that won't work for an array of structs. I also know I could brute-force it like this:

<cfset arrayIndex = 0>
<cfloop from="1" to="#ArrayLen(myArray)#" index="counter">
    <cfif myArray[counter].name IS "WhatImLookingFor">
        <cfset arrayIndex = counter>
    </cfif>
</cfloop>

...but I feel like there must be a more efficient way. Does anyone have a better solution than this? You can assume that the "name" property is present in every struct and there are no gaps or other objects in the array.

A: 

Without looking at it too deeply, I would consider converting the structure to a query (below) and then doing do a query of a query.. assuming your dataset isn't too huge!

http://www.bennadel.com/blog/264-Ask-Ben-Converting-A-Struct-To-A-Query-And-More-Java-.htm

Do share what you ended up doing!

Edit: The StructFindValue suggested looks to be excellent as well, I didn't think to look up any relevant functions.

Jas Panesar
A: 

CFGroovy FTW! :)

<cfset count = 0>
<g:script>
count = myArray.find({ 
  it["NAME"] == "WhatImLookingFor" }
})
</g:script>

or.. if you like a more java style (w/o closure)

<cfset count = 0>
<g:script>
for (i in myArray) {
  if( i["NAME"] == "WhatImLookingFor" )
    count++
}
</g:script>
Henry
Is this solution any better than the original algorithm posted in the question? I'm not well read on Groovy (or CFGroovy) yet, but it *looks* like you've just re-written the same algorithm in another language. For what it's worth, that is slightly more readable, and arguably more elegant... but it's chances of being faster are (probably) slim-to-none, considering it has to shell out to Groovy to run, and return to CF. I suppose if it's tremendously faster in Groovy then it's possible the overhead is worth it, but I doubt it.
Adam Tuttle
+5  A: 

Unless you have a hash table you're creating as you build the array, I don't see how you're going to create a search function that is faster than the O(n) solution you've posted. Anyway, while you are building your arrays, you could do something like this:

<cfloop query="qryValues">
    <cfset nameValues[name] = currentrow />
    <cfset myArray[currentrow].name = name />
</cfloop>

<cfset arrayIndex = nameValues["WhatImLookingFor"] />

This assumes that the value always exists. You may need to check StructKeyExists(nameValues, "WhatImLookingFor") before making the call.

Soldarnal
That's a good idea! I'll use that in the future.
Joshua Carmody