Reputation: 411
This is my current array
0:{modelNumber: "123456789", balance: { amount:1000, currency:"EUR" }}
1:{modelNumber: "987654321", balance: { amount:2000, currency:"EUR" }}
2:{modelNumber: "322353466", balance: { amount:1500, currency:"GBP" }}
3:{modelNumber: "892347522", balance: { amount:1000, currency:"USD" }}
4:{modelNumber: "931883113", balance: { amount:3000, currency:"INR" }}
5:{modelNumber: "854300564", balance: { amount:2500, currency:"GBP" }}
6:{modelNumber: "931883113", balance: { amount:3000, currency:"INR" }}
7:{modelNumber: "854300564", balance: { amount:3500, currency:"USD" }}
I'm trying to return a new array, with each currency and the total value for each currency.
Like below return the total amount for each currency in the array above
0:{currency: "EUR", totalAmount: 3500}
1:{currency: "GBP", totalAmount: 5000}
2:{currency: "USD", totalAmount: 4500}
3:{currency: "INR", totalAmount: 6000}
My approach initially:
//the current array
let theInitialArray = state.vehicle;
const results = theInitialArray.reduce((accumalator, current) => {
const { currency } = current.balance;
if (accumalator[currency]) {
accumalator[currency].push(current);
return accumalator;
}
accumalator[currency] = [current];
return accumalator;
}, {});
let frank = Object.keys(results)
let jim = [];
let expectedOutput = theInitialArray.filter((x) => {
for (let i=0; i < frank.length; i++) {
if (x.balance.currency === frank[i]) {
jim.push({'currency': frank[i], 'amount': x.balance.amount});
}
}
});
console.log('expectedOutput', expectedOutput)
return expectedOutput
Upvotes: 10
Views: 605
Reputation: 1712
A simple solution with Array.prototype.reduce
and Object.keys
:
const data = [
{modelNumber: "123456789", balance: { amount:1000, currency:"EUR" }},
{modelNumber: "987654321", balance: { amount:2000, currency:"EUR" }},
{modelNumber: "322353466", balance: { amount:1500, currency:"GBP" }},
{modelNumber: "892347522", balance: { amount:1000, currency:"USD" }},
{modelNumber: "931883113", balance: { amount:3000, currency:"INR" }},
{modelNumber: "854300564", balance: { amount:2500, currency:"GBP" }},
{modelNumber: "931883113", balance: { amount:3000, currency:"INR" }},
{modelNumber: "854300564", balance: { amount:3500, currency:"USD" }}
];
const grouped = data.reduce((o, { balance: { amount:a, currency:c } }) =>
({...o, [c]: (o[c] || 0) + a }), {});
const result = Object.keys(grouped).map(currency =>
({currency, totalAmount: grouped[currency] }));
console.log(result);
Upvotes: 1
Reputation: 57
This uses two arrays and pushes the unique names of the currencies in one(currencies) and the objects in another (result).
a = [{modelNumber: "123456789", balance: { amount:1000, currency:"EUR" }}, {modelNumber: "987654321", balance: { amount:2000, currency:"EUR" }},{modelNumber: "322353466", balance: { amount:1500, currency:"GBP" }},{modelNumber: "892347522", balance: { amount:1000, currency:"USD" }},{modelNumber: "931883113", balance: { amount:3000, currency:"INR" }},{modelNumber: "854300564", balance: { amount:2500, currency:"GBP" }},{modelNumber: "931883113", balance: { amount:3000, currency:"INR" }},{modelNumber: "854300564", balance: { amount:3500, currency:"USD" }}]
let currencies = [], result = [];
a.map((v)=>{
let {currency, amount} = v.balance;
if(!currencies.includes(currency)){
currencies.push(currency);
result.push({currency, totalAmount:amount});
}else{
result[currencies.findIndex(vv=>vv===currency)].totalAmount+=amount;
}
})
Upvotes: 0
Reputation: 2137
My solution with native array methods map, filter and reduce
const res = arr
// map to currency
.map(i => i.balance.currency)
// get unique currency
.filter((v, i, a) => a.indexOf(v) === i)
// map to result
.map((i, a) => ({
currency: i,
totalAmount: calcTotalAmount(i)
}));
// calculate amount
function calcTotalAmount(currency) {
return (
arr
// filter to current curency
.filter(i => i.balance.currency === currency)
// reduce to number
.reduce((accum, i) => accum + i.balance.amount, 0)
);
}
Upvotes: -1
Reputation: 386604
You could take a Map
and render the wanted array of currency
/totalAmount
pairs as new objects.
var data = [{ modelNumber: "123456789", balance: { amount: 1000, currency: "EUR" } }, { modelNumber: "987654321", balance: { amount: 2000, currency: "EUR" } }, { modelNumber: "322353466", balance: { amount: 1500, currency: "GBP" } }, { modelNumber: "892347522", balance: { amount: 1000, currency: "USD" } }, { modelNumber: "931883113", balance: { amount: 3000, currency: "INR" } }, { modelNumber: "854300564", balance: { amount: 2500, currency: "GBP" } }, { modelNumber: "931883113", balance: { amount: 3000, currency: "INR" } }, { modelNumber: "854300564", balance: { amount: 3500, currency: "USD" } }],
result = Array.from(
data.reduce((m, { balance: { amount, currency } }) =>
m.set(currency, (m.get(currency) || 0) + amount), new Map),
([currency, totalAmount]) => ({ currency, totalAmount })
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 0
Reputation: 6467
It's possible to reduce the values you have and them map them into the format you require:
const values = [
{modelNumber: "123456789", balance: { amount:1000, currency:"EUR" }},
{modelNumber: "987654321", balance: { amount:2000, currency:"EUR" }},
{modelNumber: "322353466", balance: { amount:1500, currency:"GBP" }},
{modelNumber: "892347522", balance: { amount:1000, currency:"USD" }},
{modelNumber: "931883113", balance: { amount:3000, currency:"INR" }},
{modelNumber: "854300564", balance: { amount:2500, currency:"GBP" }},
{modelNumber: "931883113", balance: { amount:3000, currency:"INR" }},
{modelNumber: "854300564", balance: { amount:3500, currency:"USD" }},
];
const results = values.reduce((prev, curr) => ({
...prev,
[curr.balance.currency]: (prev[curr.balance.currency] || 0) + curr.balance.amount
}), {})
const inCorrectFormat = Object.keys(results).map(key => ({
currency: key,
totalAmount: results[key]
}))
console.dir(inCorrectFormat)
Upvotes: 0
Reputation: 191976
You can Array.reduce()
to iterate the data. If a currency doesn't exist in the accumulator (r
in the reduce callback), initialize it. Add the current amount, to the currency amount in the accumulator. Get an array of currencies using Object.values
:
const data = [{"modelNumber":"123456789","balance":{"amount":1000,"currency":"EUR"}},{"modelNumber":"987654321","balance":{"amount":2000,"currency":"EUR"}},{"modelNumber":"322353466","balance":{"amount":1500,"currency":"GBP"}},{"modelNumber":"892347522","balance":{"amount":1000,"currency":"USD"}},{"modelNumber":"931883113","balance":{"amount":3000,"currency":"INR"}},{"modelNumber":"854300564","balance":{"amount":2500,"currency":"GBP"}},{"modelNumber":"931883113","balance":{"amount":3000,"currency":"INR"}},{"modelNumber":"854300564","balance":{"amount":3500,"currency":"USD"}}];
const result = Object.values(data.reduce((r, { balance }) => {
const { amount, currency } = balance;
if(!r[currency]) r[currency] = { currency, amount: 0 };
r[currency].amount += amount;
return r;
}, {}));
console.log(result);
Upvotes: 8
Reputation: 30739
Here is a O(n)
approach of getting that output:
tempObj
which will be used to store the currency
and totalAmount
value as a object based on the currency
keycurrency
key is defined in the tempObj
you will simply add the amount
with the totalAmount
for an existing object.amount
as totalAmount
, currency
as key
of tempObj
and currency
as currency
of the item in forEach
loopObject.values(tempObj)
so that we get the object values and ignore the keys of tempObj
to get the desired result.var arr = [{modelNumber: "123456789", balance: { amount:1000, currency:"EUR" }},
{modelNumber: "987654321", balance: { amount:2000, currency:"EUR" }},
{modelNumber: "322353466", balance: { amount:1500, currency:"GBP" }},
{modelNumber: "892347522", balance: { amount:1000, currency:"USD" }},
{modelNumber: "931883113", balance: { amount:3000, currency:"INR" }},
{modelNumber: "854300564", balance: { amount:2500, currency:"GBP" }},
{modelNumber: "931883113", balance: { amount:3000, currency:"INR" }},
{modelNumber: "854300564", balance: { amount:3500, currency:"USD" }}];
var tempObj = {};
arr.forEach((obj)=>{
if(tempObj[obj.balance.currency]){
tempObj[obj.balance.currency].totalAmount += obj.balance.amount
} else {
tempObj[obj.balance.currency] = {
currency: obj.balance.currency,
totalAmount : obj.balance.amount
}
}
});
var resArray = Object.values(tempObj);
console.log(resArray);
Upvotes: 8