0

I have an array of n objects in it. Each object has names as id, quantity, price and total. All of these have significance in solving this problem.

How can I create new arrays where sum of all total of their objects doesn't exceed 150.

My array:

let array = [{id: 1, quantity: 5, price: 10, total: 50}, {id: 2, quantity: 3, price: 100, total: 300}]

Expected result:

array1 = [{id: 1, quantity: 5, price: 10, total: 50}, {id: 2, quantity: 1, price: 100, total: 100}]
array2 = [{id: 2, quantity: 1, price: 100, total: 100}]
array3 = [{id: 2, quantity: 1, price: 100, total: 100}]

Conditions:

  1. As mentioned, sum of totals in new arrays mustn't exceed 150
  2. value of total must always be product of quantity and price in that object
  3. object must keep dividing itself into new objects with smaller quantities until above conditions are met
  4. quantity must be an integer

i tried this.

const itemsFinals = [];
const maxTotal = 150;
let totalGroup = 0;
for (i = 0; i < itemComprobantes.length; i++) {
    if((itemComprobantes[i].total  + totalGroup) < maxTotal){
        itemsFinals.push(itemComprobantes[i]);
        totalGroup += itemComprobantes[i].total;
    }
}
Elletlar
  • 3,136
  • 7
  • 32
  • 38
DarkFenix
  • 706
  • 1
  • 13
  • 34
  • why `itemComprobantes[0]` not `itemComprobantes[i]`? it means every loop you're just taking the first element of the array in your current `for loop` – threeFatCat Nov 13 '20 at 04:39
  • also this `(itemComprobantes[0].total + totalGroup)` ? – threeFatCat Nov 13 '20 at 04:41
  • Does this answer your question? [Partitioning weighted elements with a restriction on total partition weight](https://stackoverflow.com/questions/56808877/partitioning-weighted-elements-with-a-restriction-on-total-partition-weight) – Gershom Maes Nov 13 '20 at 04:43
  • are we talking about the **total amount** is the `total` key of each object or the *total* number of elements in array? isn't not that your `totalGroup` should be adding the `total` key only and not the whole object like this? `totalGroup += itemComprobantes[i].total`? – threeFatCat Nov 13 '20 at 04:46

2 Answers2

0

let itemComprobantes = [
    {id: 1, quantity: 5, price: 10, total: 50}, 
    {id: 2, quantity: 1, price: 100, total: 100},
    {id: 3, quantity: 1, price: 100, total: 100},
    {id: 4, quantity: 1, price: 100, total: 30},
    {id: 5, quantity: 1, price: 100, total: 80}
  ]

    
    const itemsFinals = {}
    const maxTotal = 150
    let totalGroup = 0
    let group = 1
    
    for (i = 0; i < itemComprobantes.length; i++) {
        if((itemComprobantes[i].total  + totalGroup) > maxTotal){
          group += 1
          totalGroup = 0
        }
        if (itemsFinals['group '+group] === undefined) {
         itemsFinals['group '+group] = []
        }
        itemsFinals['group '+group].push(itemComprobantes[i])
        totalGroup += itemComprobantes[i].total
        
    }
    
    console.log(itemsFinals)

Here is my answer base on my comments.

threeFatCat
  • 840
  • 13
  • 30
  • Thank you, but the expected result is not achieved. – DarkFenix Nov 13 '20 at 05:05
  • Can you give more detail on your question? why in your snippet the `maxTotal` is `150` but the first snippet in your question is total of `350`? `let array = [{id: 1, quantity: 5, price: 10, total: 50}, {id: 2, quantity: 3, price: 100, total: 300}]` – threeFatCat Nov 13 '20 at 05:11
  • The sum of the totals of each array must not exceed 150 if it exceeds, it is added to the next one. – DarkFenix Nov 13 '20 at 05:13
  • I think OP wants you to enter data on the first snippet and get result of second snippet – Reyot Nov 13 '20 at 06:37
0

Here is one way to do it. I know its long but give it a try

let array = [{id: 1, quantity: 5, price: 10, total: 50}, {id: 2, quantity: 3, price: 100, total: 300}, {id: 3, quantity: 5, price: 40, total: 200}, {id: 4, quantity: 2, price: 10, total: 20}];

const maxTotal = 150;
let new_arrays = {};
let index = 0;

let final_total = 0;
new_arrays['array_'+index] = [];


for (var obj of array) {
    final_total += obj.total;
    while (final_total > maxTotal) {
        let exceed_value = final_total - maxTotal;      // 350 - 150 = 200
        let retain_quantity = parseInt((obj.total - exceed_value) / obj.price); // (300 - 200)/100 = 2
        let remaining_quantity = obj.quantity - retain_quantity;
        
        if (retain_quantity != 0) {
            retain_obj = Object.assign({}, obj);
            retain_obj.quantity = retain_quantity;
            retain_obj.total = retain_quantity * obj.price;
            new_arrays["array_"+index].push(retain_obj);
        }

        index++;
        new_arrays['array_'+index] = [];
        new_obj = Object.assign({}, obj, {quantity: remaining_quantity, total: remaining_quantity * obj.price})
        new_arrays["array_"+index].push(new_obj);

        // console.log(new_obj);
        obj = new_obj;
        final_total = remaining_quantity * obj.price;

        new_arrays['array_'+index].pop();   // if loop is to repeat again
    }

    new_arrays["array_"+index].push(obj);   // prints new and remaining quantities
}
console.log(new_arrays)
Reyot
  • 466
  • 1
  • 3
  • 9