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
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
Share
Improve this question
edited Sep 22, 2018 at 17:16
themanwiththemasterplan
asked Sep 18, 2018 at 8:35
themanwiththemasterplanthemanwiththemasterplan
4112 gold badges7 silver badges23 bronze badges
1
|
7 Answers
Reset to default 8Here is a O(n)
approach of getting that output:
- You first define a empty object
tempObj
which will be used to store thecurrency
andtotalAmount
value as a object based on thecurrency
key - Then, if this
currency
key is defined in thetempObj
you will simply add theamount
with thetotalAmount
for an existing object. - Else you will create a object with the
amount
astotalAmount
,currency
askey
oftempObj
andcurrency
ascurrency
of the item inforEach
loop - Finally you will need to do
Object.values(tempObj)
so that we get the object values and ignore the keys oftempObj
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);
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);
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);
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)
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; }
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;
}
})
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)
);
}
{ "EUR": 3000, "GBP": 4000, "USD": 4500, "INR": 6000 }
as output? It would hold the exact same information and would be much easier to work with. – Eric Duminil Commented Sep 18, 2018 at 11:21