ArrayDeleteAt() issue

This may seem like a simple problem, but for some reason I’m having a brain fart and just can’t wrap my head around it.

I’m working on a very simple cart project and am using an array of structures in the session scope:

session.cart[1]
session.cart[2]
session.cart[3]
session.cart[4]

Each element in the array is a struct, as I mentioned:

session.cart[n].ID
session.cart[n].SKU
session.cart[n].PRICE
session.cart[n].QUANTITY
session.cart[n].TOTAL

If someone wants to remove an item from their cart, they can set the quantity to 0. Upon submission I loop through the array, checking for val(form.quantity_n). If it returns false, I do arrayDeleteAt(session.cart,n)

The problem arises if I loop through the array using arrayLen(session.cart), which is now one less than arrayLen() was when the loop started, since arrayDeleteAT() pulls the item out of the array and renumbers everything.

In other words, if there were three elements in the array, the loop wants to go from 1 to 3, but since element 1 was removed, the arrayLen is now only 2, total, and the loop throws an error because element 3 no longer exists.

Perhaps I should just create a new array of structures as I loop through, copying over the stay-in-cart items, and then destroying and recreating the cart array from the temp array?

What do other people do?

Thanks,

Mik

Yeah, that was it…

<cfloop from="1" to="#arrayLen(session.cart)#" index="ll">
	<cfset session.cart[ll].QUANTITY = val(evaluate("form.quantity_#ll#"))>
	<cfset session.cart[ll].TOTAL = val(evaluate("form.quantity_#ll#")) * session.cart[ll].PRICE>
</cfloop>
<cfset tempCart = arrayNew(1)>
<cfset tempCount = 0>
<cfloop from="1" to="#arrayLen(session.cart)#" index="ll">
	<cfif val(session.cart[ll].QUANTITY)>
		<cfset tempCount = tempCount + 1>
		<cfset tempCart[tempCount] = session.cart[ll]>
	</cfif>
</cfloop>
<cfscript>arrayClear(session.cart);</cfscript>
<cfset session.cart = ArrayNew(1)>
<cfset session.cart = tempCart>
<cfscript>arrayClear(tempCart);</cfscript>

Gotta be an easier way to loop through an array and safely remove elements.

Checkout array filter

https://docs.lucee.org/reference/objects/array/filter.html

1 Like

Populate the cart however you like…

// populate cart
mocksession.cart = [ 
	{
		ID: "1234",
		SKU: "9876543",
		PRICE: "10.00",
		QUANTITY: 1
	},
	{
		ID: "1235",
		SKU: "8765432",
		PRICE: "5.00",
		QUANTITY: 0
	},
	{
		ID: "1236",
		SKU: "7654321",
		PRICE: "3.00",
		QUANTITY: 2
	}
];
dump(mocksession);

Filter the array for the things you want…

// remove zero quantity items
mocksession.cart = mocksession.cart.filter( (item) => item.quantity > 0 );
dump(mocksession);

Uhhhh… loop backwards?

<cfloop from="#arrayLen(session.cart)#" to="1" step="-1" index="ll">

Problem solved.