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.
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.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:
Initialise an object to use for storing the keys (names) and values (some more objects)
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.
Update the values of that object where appropriate
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))