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?

4 Answers 4

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>
Sign up to request clarification or add additional context in comments.

2 Comments

Also shouldn't <cfif accPresent EQ "yes" and prodPresent EQ "no"> be <cfif accPresent EQ "yes" and prodPresent EQ "yes">
Also the second <cfif could just be an else assuming .accs is only ever yes or no
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.

4 Comments

(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.
Actually I misread the question ;) I thought they were only concerned with two conditions (hasAccessories=true/false) so cfbreak made more sense there.
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>
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!!
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

Comments

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.