Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Finding variable in array

Status
Not open for further replies.

JamesManke

Programmer
Jul 1, 2004
54
CA
EXAMPLE:

session.cart[1].id = 23
session.cart[2].id = 54
session.cart[3].id = 76

What is a function that can find a certain id. What I want to do is scan the array and see if a certain id remains in the array. For example, if I scanned the array shown and asked if id number 54 was in it, it would give a true/false or 0/1 value.

Thanks for your help,
James
 
<cfif listFind(arrayToList(session.cart), "54"><cfset flag = 1><cfelse><cfset flag = 0>

or something to that effect.

If the automobile had followed the same development cycle as the computer, a Rolls-Royce would today cost $100, get a million miles per gallon, and explode once a year, killing everyone inside.
 
JamesManke,

Try using this solution:

Code:
<!--- Copy your cart from session to a local scope to prevent race conditions --->
<cflock scope="session" type="readOnly" timeout="10">
     <cfset tmpCart = duplicate(session.cart)>
</cflock>

<!--- Loop over your cart for an item id --->
<cfset myTargetId = ? >
<cfset hasTargetId = false>
<cfloop from="1" to="#arrayLen(tmpCart)#" index="i">
   <cfif tmpCart[i].id EQ myTargetId>
       <cfset hasTargetId = true>
   </cfif>
</cfloop>

<!-- hasTargetID contains the 'truth' of your id lookup --->

jalpino
 
That seems like an awful lot of saving, setting, and looping when you could just scan through a list as cannedRadio suggested. Even though you would get the same results, the first solution uses much less processing so it should be better on performance.



Hope This Helps!

ECAR
ECAR Technologies, LLC

"My work is a game, a very serious game." - M.C. Escher
 
ECAR,

If you notice, the session.cart variable described is an array of structures. You cannot convert an array of complex objects to a list, like cannedRadio is suggesting. Did you try running that snippet of code using the session.cart variable jamesManke supplied? It doesn't work.

Also CF can process arrays much faster than lists, over large data sets looping through the array will perform better than the listFind() function. You should read this article.

ColdFusion MX Coding Guidelines - Appendix: Performance Techniques

jalpino
 
oops i didn't see the .id after the array, good catch.

I read page you suggested and it said:
livedocs said:
listGetAt() is not an efficient way to work with individual items in a data set!

however we were not working with a single element, and i also never believe anything about efficiency until i test it myself... i ran a test in cfmx 6.1

Code:
<cfset myArray = arrayNew(1)>
<cfloop from = "1" to = "10000" index = "count">
	<cfset myArray[count] = count>
</cfloop>
<cfset foundInArray = false>
<cfset arrayTime1 = getTickCount()>
<cfloop from="1" to="#arrayLen(myArray)#" index="i">
   <cfif myArray[i] EQ 54>
       <cfset foundinarray = true>
       [COLOR=gray]<cfabort>[/color]
   </cfif>
</cfloop>
<cfif foundinarray>
	found in array<br>
<cfelse>
	not found in array<br>
</cfif>
<cfset arrayTime2 = getTickCount()>
<br>
<cfset listTime1 = getTickCount()>
<cfif listFind(arrayToList(myArray), "54")>
	found in list<br>
<cfelse>
	not found in list<br>
</cfif>
<cfset listTime2 = getTickCount()>
<cfset arrayTicks = (arrayTime2-arraytime1)>
<cfset listTicks = (listTime2-listTime1)>
<br>
<cfoutput>
	searching the 10000 index array took #arrayTicks# ticks<br>
	searching the 10000 index array using listfind(arraytolist(array),value) took #listTicks# ticks<br>
</cfoutput>

i found using listfind(arraytolist),value) was typically about 4 times faster than looping through the array.

using cfbreak once the number was found DID speed up the array loop though.

using cfbreak, looking for a small number like 54 took 0 ticks.
using cfbreak, looking for 7985 took an average of 47 ticks.
not using cfbreak the average took an average of 61 ticks to get any number looping over the entire array.
using listfind(arraytolist(array),value) took an average of 16 ticks no matter what number you were looking for.

to be fair livedocs also said "working with strings is slow in java."(way to go java) i added "a" after the numbers to make the data in each element a string not a number. my findings were the same.

If the automobile had followed the same development cycle as the computer, a Rolls-Royce would today cost $100, get a million miles per gallon, and explode once a year, killing everyone inside.
 
cannedRadio,

Using <cfbreak> to halt the execution of the loop is definitely a smart choice and will prevent unneccesary processing.

However just out of curiosity, I copied your code ,swapped out the <cfabort> in the first loop with a <cfbreak> tag and also included an arrayResize() function call, as recommended by Macromedia for arrays larger than 500 indexes.

The results I got back were different from yours. I ran your script looking for target numbers of 100 and 9999 to get an idea of both ends of the spectrum and in every case, the array lookup performed better.

What version of CF are you testing on?

jalpino
 
hi jalpino,

i'm assuming you knew i ment cfbreak when i put cfabort in the post. sorry about that.

i put the page on a public site for testing. i made it use url variables so you can choose the number to search for. yes with a smaller number the array loop does much better using cfbreak, like i said 0 - 16 :).

the following page has 4 tests
1 same code as above NO CFBREAK
2 same code as test 1 includeing arrayResize()
3 same code as test 1 with cfbreak
4 same code as test 2 with cfbreak

I also did a cfdump of the server var so you can see what's running.

the page:

text version of page (view source to see cfm code):

disregarding wild values, the list usualy comes out a head.

what are your thoughts?



If the automobile had followed the same development cycle as the computer, a Rolls-Royce would today cost $100, get a million miles per gallon, and explode once a year, killing everyone inside.
 
I'm anxious to know your input. this has been an educational post thus far, thanks.

If the automobile had followed the same development cycle as the computer, a Rolls-Royce would today cost $100, get a million miles per gallon, and explode once a year, killing everyone inside.
 
hi cannedRadio,

I figured that you had ment <cfbreak> instead of <cfabort>, you even mentioned it in your original post and would make sense given the conditions of the test script.

For your particular test, using the ListFind() function did yield faster results (in CFMX atleast, in CF5 the results were the opposite) than the array counterpart. I was incorrect in saying that looping through an array for this particular example would be faster than using the listFind() function.

However, the point that I was trying to make is that working with arrays in general, is faster than working with lists. The engineers at Macromedia seem to agree with that statement as shown in the Coding Standards document created by them.

jalpino
 
Oh i agree. :)
far be it from me to argue with the engineers, they know best. I was just testing the "working with 1 element (which was documented to be faster)" vs "working with many elements (which didn't document)"



If the automobile had followed the same development cycle as the computer, a Rolls-Royce would today cost $100, get a million miles per gallon, and explode once a year, killing everyone inside.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top