Looping through an array using ColdFusion
Asked Answered
S

4

6

I have a shopping cart array, which has a variable to tell me if the product is an accessory or not, this will be either yes or no. I need to loop through the cart and find out the following:

  • If the cart contains accessories only; do whatever.
  • If the cart is products only; do whatever.
  • If the cart has products and accessories; do whatever.

I have been trying this:

<cfloop index="i" from="1" to="#arrayLen(session.mycart)#">
  <cfif session.mycart[i].accs EQ "yes">
    <cfset accPresent = "yes">
  </cfif>
  <cfif session.mycart[i].accs EQ "no">
    <cfset prodpresent = "yes">
  </cfif>
</cfloop>

<cfif accPresent EQ "yes" and prodPresent EQ "no">
  <cfset  bothPresent EQ "yes">
</cfif>

This falls down as accPresent is not found, this i think is due to the fact the loop goes through one at a time and the accs is not equal to yes once it find a non accessory product. What's the best way to achieve what I'm trying to do?

Sedimentary answered 12/2, 2012 at 21:7 Comment(0)
B
7

Do this

<cfset accPresent = "no" />
<cfset prodPresent = "no" />
<cfloop index="i" from="1" to="#arrayLen(session.mycart)#">
    <cfif session.mycart[i].accs EQ "yes">
        <cfset accPresent = "yes">
    </cfif>
    <cfif session.mycart[i].accs EQ "no">
        <cfset prodpresent = "yes">
    </cfif>
</cfloop>

<cfif accPresent EQ "yes" and prodPresent EQ "no">
    <cfset  bothPresent EQ "yes">
</cfif>
Bondy answered 12/2, 2012 at 21:23 Comment(2)
Also shouldn't <cfif accPresent EQ "yes" and prodPresent EQ "no"> be <cfif accPresent EQ "yes" and prodPresent EQ "yes">Bondy
Also the second <cfif could just be an else assuming .accs is only ever yes or noBondy
V
3

Jason,

Your 3rd statement assumes that AccPresent and ProdPresent will both exist. Did you create them first and give them default values? Try this:

<cfparam name="accPresent" default="no"/>
<cfparam name="prodPresent" default="no"/>
<cfloop index="i" from="1" to="#arrayLen(session.mycart)#">
<cfif session.mycart[i].accs EQ "yes">
<cfset accPresent = "yes">
</cfif>
<cfif session.mycart[i].accs EQ "no">
<cfset prodpresent = "yes">
</cfif>
</cfloop>    
<cfif accPresent EQ "yes" and prodPresent EQ "no">
<cfset  bothPresent EQ "yes">
</cfif>

This assumes of course that each of these should be set to "no" by default.

Video answered 12/2, 2012 at 21:27 Comment(4)
(leigh suggested a CFBREAK as well. That's a good thought - but I suspect that a shopping cart would have a pretty small array, so you would not getting any performance kick out of that. Still, it would actually be the most efficient way to go with 2 loops. As soon as you have a "yes" you break out of the loop and move on to the next block.Video
Actually I misread the question ;) I thought they were only concerned with two conditions (hasAccessories=true/false) so cfbreak made more sense there.Pyroelectricity
Though if it is a small array, they could just count the number of each. Then use the counts to determine if both are present ie <cfif accessoryCount and productCount>has both </cfif>Pyroelectricity
Thanks for your answers, both answers are correct!! I have selected the first as correct and voted up the second answer! Completely forgot to declare the variables! Tired eyes!!! Generally this cart will only have a max of two products, so performance should be good!!Sedimentary
D
2

In versions of ColdFusion 8 and higher, a <cfloop> can use an array directly

<cfloop index="i" array="#session.mycart#">
  <cfif i.accs EQ "yes">
    <cfset accPresent = "yes">
  </cfif>
  <cfif i.accs EQ "no">
    <cfset prodpresent = "yes">
  </cfif>
</cfloop>

<cfif accPresent EQ "yes" and prodPresent EQ "no">
  <cfset  bothPresent EQ "yes">
</cfif>

Note: That i refers to the struct containing the data, not position of the data

http://livedocs.adobe.com/coldfusion/8/htmldocs/help.html?content=Tags_j-l_15.html

Dissuasive answered 7/5, 2014 at 20:54 Comment(0)
V
1

In CF 10 (or Railo 4), this can be done more elegantly using cfscript and the Underscore.cfc library:

_ = new Underscore();

myCart = duplicate(session.myCart);

accPresent = _.any(myCart, function(val) {
    return val.accs;
});

prodPresent = _.any(myCart, function(val) {
    return !val.accs;
});

bothPresent = accPresent && prodPresent;

The great thing about _.find() is that it stops as soon as the iterator function returns true, so you don't have to iterate over every single element in the array.

Note: Using duplcate() is recommended when accessing shared-scope variables in order to prevent deadlocks.

(Disclaimer: I wrote Underscore.cfc)

Vidrine answered 6/7, 2012 at 4:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.