Home > OS >  Add/Sum multiple values of array and display using Javascript/Python
Add/Sum multiple values of array and display using Javascript/Python

Time:01-06

var input = [{id: 1, price: 1200, profit:60, name:'Messi'},
             {id: 2, price: 600, profit:40, name:'Ronaldo'},
             {id: 1, price: 100, profit:40, name:'Messi'},
             {id: 1, price: 200, profit:30, name:'Messi'},
             {id: 2, price: 400, profit:10, name:'Ronaldo'},
             {id: 1, price: 800, profit:10, name:'Messi'}];

Expected Output:

[{id:1, name:'Messi', price:'2300', profit:'140'},
 {id:2, name:'Ronaldo', price:'1000', profit:'50'},
]

Tried:

var output = { };
input.forEach(e => output[e.id] = (output[e.id] || 0)   e.price);

console.log(output);

How to make like the expected output here.

CodePudding user response:

You can do it with the .reduce() method

var input = [{
    id: 1,
    price: 1200,
    profit: 60,
    name: 'Messi'
  },
  {
    id: 2,
    price: 600,
    profit: 40,
    name: 'Ronaldo'
  },
  {
    id: 1,
    price: 100,
    profit: 40,
    name: 'Messi'
  },
  {
    id: 1,
    price: 200,
    profit: 30,
    name: 'Messi'
  },
  {
    id: 2,
    price: 400,
    profit: 10,
    name: 'Ronaldo'
  },
  {
    id: 1,
    price: 800,
    profit: 10,
    name: 'Messi'
  }
];

/* [{id:1, name:'Messi', price:'2300', profit:'140'},
 {id:2, name:'Ronaldo', price:'1000', profit:'50'}] */

var result = []; //Initialize array

//array reduce
input.reduce(function(res, value) {
  if (!res[value.name]) {
    res[value.name] = {
      id: value.id,
      name: value.name,
      price: 0,
      profit: 0
    };
    result.push(res[value.name])
  }
  res[value.name].price  = value.price; //sums price key values
  res[value.name].profit  = value.profit; //sums profit key values
  return res; //returns response
}, {});

//output
console.log(result)

CodePudding user response:

You can use Array.prototype.reduce() combined with Nullish coalescing assignment (??=)

Code:

const input = [{ id: 1, price: 1200, profit: 60, name: 'Messi' },{ id: 2, price: 600, profit: 40, name: 'Ronaldo' },{ id: 1, price: 100, profit: 40, name: 'Messi' },{ id: 1, price: 200, profit: 30, name: 'Messi' },{ id: 2, price: 400, profit: 10, name: 'Ronaldo' },{ id: 1, price: 800, profit: 10, name: 'Messi' },]

const result = input.reduce((a, c) => {
  a[c.id] ??= { id: c.id, name: c.name, price: 0, profit: 0 }
  a[c.id].price  = c.price
  a[c.id].profit  = c.profit
  return a
}, {})

console.log(Object.values(result))

CodePudding user response:

There are two key things here.

  1. You need to loop over the array of objects.

    JavaScript provides several mechanisms for looping over arrays. You can use a traditional for statement. Or a for/of statement, or perhaps reduce as mentioned in the other answers.

  2. You need to be able to group information by the name provided in the objects.

    Objects are very useful here as they allow you to associate (read: "group") values with unique keys.

So, the general procedure is:

  1. Initialise an object to use for storing the keys (names) and values (some more objects)

  2. Loop over the input array. Take the name from the object and check to see if it exists as a key in the object. If it doesn't exist add it as a key, and then assign an initial object in the iteration as its value.

  3. Update the values of that object where appropriate

  4. Well, now you have an object of objects where what you want is an array of objects again, similar to your input. Use Object.values to return an array of the object's values (the nested objects).

Note: in your question your required output has the price and profit as strings rather than numbers so you may have to do an additional mapping operation on the array from Object.values to get that result. I've included that code at the end of the example along with some links to documentation of other code mentioned.)

In this example I'll use a for/of loop.

const input=[{id:1,price:1200,profit:60,name:"Messi"},{id:2,price:600,profit:40,name:"Ronaldo"},{id:1,price:100,profit:40,name:"Messi"},{id:1,price:200,profit:30,name:"Messi"},{id:2,price:400,profit:10,name:"Ronaldo"},{id:1,price:800,profit:10,name:"Messi"}];

// Initialise an empty object
const temp = {};

// For every object in the input array...
for (const obj of input) {

  // Destructure the properties from it
  const { id, price, profit, name } = obj;

  // If the name doesn't exist as a key on the object
  // add it, and assign an initial object to it that mirrors
  // the current object in the iteration, but where the
  // values of the properties that you want to increase are
  // set to zero. The key is there just go to the next step
  temp[name] ??= { id, name, price: 0, profit: 0 };

  // Increase the price and profit values in
  // the initialised object
  temp[name].price  = price;
  temp[name].profit  = profit;
}

// Finally, after the iteration, we return
// an array of those nested objects we've created
const output = Object.values(temp);

console.log(output);

// If you want to strings for those values
// you'll have to do an additional `map` to
// stringify them
const stringified = output.map(obj => {

  // Use destructuring to get the profit and
  // price properties, and assign everything else to `rest`
  const { price, profit, ...rest } = obj;

  // Return a new object by spreading out `rest`,
  // and coercing the numbers to strings
  return {
    ...rest,
    price: price.toString(),
    profit: profit.toString()
  };

});

console.log(stringified);

Additional information

CodePudding user response:

Instead of computing just price, you can also compute profit and also add id and name, the result of each id being an object instead of a number. Then use Object.values() to get the final result. As has been demonstrated elsewhere Array#reduce can also be used to give us the intermediate result.

const input = [{id: 1, price: 1200, profit:60, name:'Messi'},
             {id: 2, price: 600, profit:40, name:'Ronaldo'},
             {id: 1, price: 100, profit:40, name:'Messi'},
             {id: 1, price: 200, profit:30, name:'Messi'},
             {id: 2, price: 400, profit:10, name:'Ronaldo'},
             {id: 1, price: 800, profit:10, name:'Messi'}];

/*Expected Output:

[{id:1, name:'Messi', price:'2300', profit:'140'},
 {id:2, name:'Ronaldo', price:'1000', profit:'50'},
]

Tried:*/

const output = { };
input.forEach(
  e => output[e.id] = {
    id: e.id,
    name: e.name,
    price:(output[e.id]?.price || 0)   e.price,
    profit:(output[e.id]?.profit || 0)   e.profit
  });

console.log(Object.values(output));

CodePudding user response:

Give this a shot :)

var input = [{id: 1, price: 1200, profit:60, name:'Messi'},
         {id: 2, price: 600, profit:40, name:'Ronaldo'},
         {id: 1, price: 100, profit:40, name:'Messi'},
         {id: 1, price: 200, profit:30, name:'Messi'},
         {id: 2, price: 400, profit:10, name:'Ronaldo'},
         {id: 1, price: 800, profit:10, name:'Messi'}];

function transform(input) {
  let output = []
  let lookup = {}

  for (let i = 0; i < input.length; i  ) {
    let item = input[i]
    let key = item.id

    if (lookup[key]) {
      lookup[key].price  = item.price
      lookup[key].profit  = item.profit
    } else {
      lookup[key] = { ...item }
    }
  }

  for (let key in lookup) {
    output.push(lookup[key])
  }

  return output
}

console.log(transform(input))

  • Related