Sort values of structure with arrays
Copy link to clipboard
Copied
Hi
For a shopping cart I'm using a structure with arrays to store the items in the cart. I tried to use StructSort but did not work...
This is how I store the items in the cart:
<cfscript>
if (not(isdefined("session.cart"))) { // Check to make sure that the Shopping cart structure exists.
session.cart = structnew();
// The item structure we are going to use to store the items in the cart
// is going to have four parts...
// 1. The item id
// 2. The item name
// 3. The price per unit
// 4. The quantity
tempvalue = listtoarray('#attributes.id#,#attributes.name#,#attributes.price#,#attributes.quantity#');
// if the item is not yet in the cart, simply add it to the cart
if (not(structKeyExists(session.cart, attributes.name))) {
StructInsert(session.cart,attributes.name,tempvalue);
}
// if the item is already in the cart, update the item quantity
else {
tempvalue[4]=session.cart[attributes.name][4]+attributes.quantity;
StructUpdate(session.cart,attributes.name,tempvalue);
}
</cfscript>
Any help will be appreciated.
Thank you.
TJ
Copy link to clipboard
Copied
Not that this answers your question, but don't you want an array of structs, not a struct of arrays?
Each element of the array would be an item in the cart, which itself would be a struct keyed on those parts you list:
Item 1:
ID: OCE1
Name: ocelot
Price: £5
Quantity: 3
Item 2:
ID: PAN6
Name: pangolin
Price: £10
Quantity: 6
etc
What is it you're trying to achieve by sorting this? What's the ordering you are after?
--
Adam
Copy link to clipboard
Copied
I don't mind to use an array of structs...is there many changes involved?
To display the cart I simply use a loop:
<cfloop collection="#session.cart#" item="i">
#session.cart[2]# #session.cart[3]# #session.cart[4]#<br>
</cfloop>
To answer your questions:
When I display the shopping cart I'd like to show the items ordered by name or by price as at the moment they don't display in any order. It displays the items in a random order. At first I thought it was in the order that you add them in the cart but that's not the case.
Copy link to clipboard
Copied
To loop over an array one has two options:
<cfloop index="i" from="1" to="#arrayLen(a)#">
Or:
<cfloop index="someVar" array="#a#">
Personally I use the former because I think the implementation of array-looping with <cfloop> is cocked-up as it's not the index that gets put into "someVar", it's the array element itself. So by way of pedantic protest, I don't use that syntax.
But anyway...
The reason why your struct is unordered is because structs are - innately, and by definition - unordered. If you want an ordered data structure, you use an array.
However what you are wanting to do is to sort your array by a subkey value of the structs the array contains. If you want to do that, you will need to roll your own sorting solution.
Personally I'd stick with using an array and just use its intrinsic ordering (the order in which items are added to it). However if you wanted to sort on one of the inner struct keys, you could maintain a separate struct keyed on the value you wish to sort on, containing a reference to the array element in the original array. Then you could extract a structKeyArray() from that, and use arraySort() to order those index keys in whichever order you like.
--
Adam
Copy link to clipboard
Copied
I'll start looking into doing an array of structs...in the mean time perhaps someone else out there knows how to sort the values of an structure of arrays.
Thanks
Copy link to clipboard
Copied
What is the key your using for the outer struct? I am finding it hard to get my brain around how you are implementing this cart as a struct of arrays.
What's some sample data?
--
Adam
Copy link to clipboard
Copied
Hi Adam
This is inherited old code that I'm trying to update...
Anyway to answer your question the key for the outer struct is the item's name. Here is a screen-shot of some sample data using cfdump. It's ironic that cfdump successfully sorts the item's name alphabetically...
I hope this extra information helps.
TJ
Copy link to clipboard
Copied
One doesn't actually sort the structure. I.E. nothing is done to the data in memory.
The structSort() function returns an array of the structKeys in sorted order.
One then loops over this array, uses the key name in each array element in turn to access the data from the original structure variable.
<cfset aStruct = [c=1,a=2,z=3,m=4]>
<cfset sortedAry = structSort(aStruct)>
<cfloop from="1" to="#arrayLen(sortedAry)#" index="i">
<cfoutput>Key: #sortedAry# Value: #aStruct[sortedAry]#</cfoutput><br/>
</cfloop>
Untested code, but that is the idea.

