1

I'm trying to iterate over an existing array with of objects with a 'quantity' property and rebuild it by a control value.

let cart = [{id: 1, name: 'Pizza', quantity: 5, specialId: 0},
            {id: 2, name: 'Burger', quantity: 2, specialId: 0}];

I have a control of 3 items i.e. for every 3 items you get a discount so I'd like to reconstitute the cart array as follows:

cart = [{id: 1, name: 'Pizza', quantity: 3, specialId: 1}, 
        {id: 2, name: 'Pizza', quantity: 2, specialId: 2},
        {id: 3, name: 'Burger', quantity: 1, specialId: 2},
        {id: 4, name: 'Burger', qty: 1, specialId: 0}]

I've looked at several ways of doing this mostly around creating a new array of single quantity items and then creating another final array but surely that isn't very efficient?

I'd appreciate any pointers. I have a horrible feeling I'm missing something simple and have stared at this too long.

10
  • 4
    Why would the Burger get split in two records when its quantity is only 2 ? Commented Oct 23, 2018 at 13:43
  • 1
    also could the initial cart contain a second record with Pizza ? Commented Oct 23, 2018 at 13:45
  • Are you sure you need to be splitting the objects in the first place? Commented Oct 23, 2018 at 13:47
  • 2
    Why quantity and qty? Commented Oct 23, 2018 at 13:48
  • 1
    I don't really know what that means "display the cart by special". Do you mean you want to identify every complete set of 3 items with a unique specialId, and attribute zero to items that are not part of a complete set? If so, please update your question in order to clarify this and other points raised in the comments section. Commented Oct 23, 2018 at 14:19

2 Answers 2

2

If I understand correctly the amount of three is ignorant of the type of product, so the second batch of three (in your example) consists of 2 pizzas and 1 burger.

The specialId seems to be unique and non-zero for every complete set of three (where every item in that set shares that specialId value), and zero for any remaining item(s).

Finally, it seems that the id in the result is unrelated to the input, but just an incremental number.

Here is how you could do that:

function splitBy(cart, size) {
    const result = [];
    let quantity = 0;
    let grab = size;
    let specialId = 1;
    let id = 1;
    for (let item of cart) {
        for (quantity = item.quantity; quantity >= grab; quantity -= grab, grab = size, specialId++) {
            if (result.length && !result[result.length-1].specialId) result[result.length-1].specialId = specialId;
            result.push(Object.assign({}, item, {quantity: grab, specialId, id: id++}));
        }
        if (quantity) result.push(Object.assign({}, item, {quantity, specialId: 0, id: id++}));
        grab = size - quantity;
    }
    return result;
}

const cart = [{id: 1, name: 'Pizza', quantity: 5, specialId: 0},
              {id: 2, name: 'Burger', quantity: 2, specialId: 0}];
const result = splitBy(cart, 3)

console.log(result);

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. That is quite clever and fast. //Attributed @trincot
0

Basically you have two options.

  1. loop over the current cart, and if the quantity is over 3, split it to two, and push them both.
  2. split the array, and then merge it together.

My guess is to go with the first option, doing something like this:

var cart = [{id: 1, name: 'Pizza', quantity: 5, specialId: 0},
    {id: 2, name: 'Burger', quantity: 2, specialId: 0}];
var a = [];

cart.forEach(x => {
 if (x.quantity > 3) {
    let temp = {...x};
    temp.quantity = 3;
    a.push(temp);
    x.quantity -= 3;
  }
  a.push(x)
});

2 Comments

Thanks. That is an interesting pointer but won't work as it will result in incorrect quantities i.e Pizza 3, Pizza 2, Burger 2
Sorry, I didn't understand your question correctly, I assumed your condition for a discount is 3 of the same product. If it doesn't have to be the same product, just change the if condition to be a counter that gets reset when it reaches 3, and then pushes the result to the array.

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.