How to sum each value inside array of object to new variable - javascript

I have a data like this :
const fund =
[
{
id: 1234,
totalAmount: 0,
data:
[
{
id: 1234,
amount: '4.000'
},
{
id: 1234,
amount: '3.000'
}
]
},
{
id: 12345,
totalAmount: 0
},
{
id: 123456,
totalAmount: 0
data:
[
{
id: 123456,
amount: '3.000'
},
{
id: 123456,
amount: '5.000'
}
]
}
]
I want to sum the amount inside of data each id to a key called totalAmount. But not all the parent id have data key.
here's my desired output :
const fund =
[
{
id: 1234
data:
[
{
id: 1234,
amount: '4.000'
},
{
id: 1234,
amount: '3.000'
}
],
totalAmount: 7000
},
{
id: 12345,
totalAmount: 0
},
{
id: 123456,
data:
[
{
id: 123456,
amount: '3.000'
},
{
id: 123456,
amount: '5.000'
}
],
totalAmount: 8000
}
]
I was trying with this code :
fund.forEach((elA, i) => {
if (elA.data) {
const total = funders[i].data.reduce((acc, curr) => {
acc += parseInt(curr.amount.replace(/\./g, ''))
return acc
})
fund[i] = total ? {...elA, totalAmount: total} : elA;
}
})
But it's not summing like i want.
Where's my mistake ?
Please ask me if you need more information if it's still not enough to solve that case.

You need to define the initial value for the reduce iterator.
fund.forEach((elA, i) => {
if (elA.data) {
const total = funders[i].data.reduce((acc, curr) => {
acc += parseInt(curr.amount.replace(/\./g, ''))
return acc
}, 0)
fund[i] = total ? {...elA, totalAmount: total} : elA;
}
});
Another alternative for the same code:
fund.forEach(elA => {
if (elA.data) {
const total = elA.data.reduce((acc, curr) => {
return acc + parseInt(curr.amount.replace(/\./g, ''))
}, 0)
elA.totalAmount = total;
}
});

Related

How to spread inner object

I have data like this
finalValue [
{ _id: { _id: 'OUTCOME_APPROUVED' }, count: 1 },
{ _id: { _id: 'OUTCOME_SWITCH_INTERFACE' }, count: 5 }
]
I want to spread the inner object and change the keys to name and value to make final value looks like this
finalValue [
{ name: 'OUTCOME_APPROUVED' , value: 1 },
{ name: 'OUTCOME_SWITCH_INTERFACE' , value: 5 }
]
try this :
var finalValue = [
{ _id: { _id: 'OUTCOME_APPROUVED' }, count: 1 },
{ _id: { _id: 'OUTCOME_SWITCH_INTERFACE' }, count: 5 }
]
var newValue = finalValue.map(({_id:{_id},count}) => {
return {name:_id , value:count}
})
console.log(newValue)
[JS]
You could use map instead of spreading, and not sure about how you could spread it to format it the way you want.
const inputValue = [ { _id: { _id: 'OUTCOME_APPROUVED' }, count: 1 },
{ _id: { _id: 'OUTCOME_SWITCH_INTERFACE' }, count: 5 }]
const computedValue = inputValue.map((data) => {
return { name: data._id._id, value: data.count };
});

Return last value with recursion - Javascript

Hi all I have following data:
const section = {
fileds: [
{ id: "some Id-1", type: "user-1" },
{
child: [
{ id: "some Id-2", type: "user-2" },
{ fileds: [{ id: "kxf5", status: "pending" }] },
{ fileds: [{ id: "ed5t", status: "done" }] }
]
},
{
child: [
{ id: "some Id-3", type: "teacher" },
{ fileds: [{ id: "ccfr", status: null }] },
{ fileds: [{ id: "kdpt8", status: "inProgress" }] }
]
}
]
};
and following code:
const getLastIds = (arr) =>
arr.flatMap((obj) => {
const arrayArrs = Object.values(obj).filter((v) => Array.isArray(v));
const arrayVals = Object.entries(obj)
.filter(([k, v]) => typeof v === "string" && k === "id")
.map(([k, v]) => v);
return [...arrayVals, ...arrayArrs.flatMap((arr) => getLastIds(arr))];
});
console.log(getLastIds(section.fileds));
// output is (7) ["some Id-1", "some Id-2", "kxf5", "ed5t", "some Id-3", "ccfr", "kdpt8"]
My code doing following, it printing in new array all ids.
It's working but I don't need all ids.
I need to return only last id in array and I should use recursion.
The output should be
(4) [" "kxf5", "ed5t", "ccfr", "kdpt8"]
P.S. here is my code in codesandbox
Is there a way to solve this problem with recursion? Please help to fix this.
You can do it with reduce.
function getLastIds (value) {
return value.reduce((prev, cur) => {
if (cur.id) {
return [ ...prev, cur.id ];
} else {
let key = ('child' in cur) ? 'child' : 'fileds';
return [ ...prev, ...getLastIds (cur[key]) ]
}
}, []);
}
You could check if a certain key exists and take this property for mapping id if status exists.
const
getValues = data => {
const array = Object.values(data).find(Array.isArray);
return array
? array.flatMap(getValues)
: 'status' in data ? data.id : [];
},
section = { fileds: [{ id: "some Id-1", type: "user-1" }, { child: [{ id: "some Id-2", type: "user-2" }, { fileds: [{ id: "kxf5", status: "pending" }] }, { fileds: [{ id: "ed5t", status: "done" }] }] }, { child: [{ id: "some Id-3", type: "teacher" }, { fileds: [{ id: "ccfr", status: null }] }, { fileds: [{ id: "kdpt8", status: "inProgress" }] }] }] },
result = getValues(section);
console.log(result);

How to Group JavaScript Array of Object based on key

So I have a data like this
const carts = [
{
name: 'Voucher A',
participants: [
{
date: 112
},
{
date: 112
}
],
supplierName: 'ABC',
ticketDescription: 'Description of',
...data
},
{
name: 'Voucher B',
participants: [
{
date: 111
},
{
date: 112
}
],
supplierName: 'ABC',
ticketDescription: 'Description of',
...data
}
]
And I want to group it based on the date (if it has same date). So for data above, the expected result will be
expected = [
{
name: 'Voucher A',
date: 1,
count: 1,
supplierName: 'ABC',
ticketDescription: 'Description of',
...data
},
{
name: 'Voucher A',
date: 2,
count: 1,
supplierName: 'ABC',
ticketDescription: 'Description of',
...data
}
]
Because it has different date. But if it has same date, the expected result will be
expected = [
{
name: 'Voucher A',
date: 1,
count: 2,
supplierName: 'ABC',
ticketDescription: 'Description of',
...data
}
]
I was trying to use reduce to group it but it did not give the structure I want
carts.forEach(cart => {
cart.participants.reduce((acc, obj) => {
acc[obj.date] = [...acc[obj.date] || [], obj]
return acc
}, {})
})
To organize the data, I think you need two associations to group by: the name and the dates and their counts for that name:
const carts = [
{
name: 'Voucher A',
participants: [
{
date: 1
},
{
date: 2
}
]
}
];
const groupedByNames = {};
for (const { name, participants } of carts) {
if (!groupedByNames[name]) groupedByNames[name] = {};
for (const { date } of participants) {
groupedByNames[name][date] = (groupedByNames[name][date] || 0) + 1;
}
}
const output = Object.entries(groupedByNames).flatMap(
([name, dateCounts]) => Object.entries(dateCounts).map(
([date, count]) => ({ name, date: Number(date), count })
)
);
console.log(output);
If you want use, just plain for loops, you can try this solution. It looks simple and elegant 😜😜
const carts = [
{
name: 'Voucher A',
participants: [
{
date: 1
},
{
date: 1
},
{
date: 2
}
]
},
{
name: 'Voucher B',
participants: [
{
date: 1
},
{
date: 2
},
{
date: 2
}
]
}
]
const finalOutput = []
for (const cart of carts) {
for (const participant of cart.participants) {
const res = finalOutput.find(e => e.name === cart.name && e.date === participant.date)
if (res) {
res.count += 1
} else {
finalOutput.push({ name: cart.name, date: participant.date, count: 1 })
}
}
}
console.log(finalOutput)
Use forEach and destructuring
const process = ({ participants, name }) => {
const res = {};
participants.forEach(({ date }) => {
res[date] ??= { name, count: 0, date };
res[date].count += 1;
});
return Object.values(res);
};
const carts = [
{
name: "Voucher A",
participants: [
{
date: 1,
},
{
date: 2,
},
],
},
];
console.log(carts.flatMap(process));
const carts2 = [
{
name: "Voucher A",
participants: [
{
date: 1,
},
{
date: 1,
},
],
},
];
console.log(carts2.flatMap(process));

find() inside reduce() method returns undefined

I have two arrays of objects; districts and userCounts. I am trying to reduce districts and find userCounts inside reduce
const result = districts.reduce((acc, curr) => {
const findUser = userCounts.find(({ _id }) => _id === curr._id)
console.log(findUser)
})
all findUser is returning undefined
districts:
[
{
_id: '5efc41d74664920022b6c016',
name: 'name1'
},
{
_id: '5efc41a44664920022b6c015',
name: 'name2'
},
{
_id: '5efc2d84caa7964dcd843a7b',
name: 'name3'
},
{
_id: '5efc41794664920022b6c014',
name: 'name 4'
}
]
userCounts:
[
{ _id: '5efc2d84caa7964dcd843a7b', totalCount: 3 },
{ _id: '5efc41794664920022b6c014', totalCount: 1 }
]
well .filter() with .every() is better use case here
let districts = [
{
_id: "5efc41d74664920022b6c016",
name: "name1",
},
{
_id: "5efc41a44664920022b6c015",
name: "name2",
},
{
_id: "5efc2d84caa7964dcd843a7b",
name: "name3",
},
{
_id: "5efc41794664920022b6c014",
name: "name 4",
},
];
let userCounts = [
{ _id: "5efc2d84caa7964dcd843a7b", totalCount: 3 },
{ _id: "5efc41794664920022b6c014", totalCount: 1 },
];
const result = districts.filter((dist) => {
return userCounts.some(({ _id }) => _id === dist._id);
});
console.log(result);
const districs=[
{
_id: '5efc41d74664920022b6c016',
name: 'name1'
},
{
_id: '5efc41a44664920022b6c015',
name: 'name2'
},
{
_id: '5efc2d84caa7964dcd843a7b',
name: 'name3'
},
{
_id: '5efc41794664920022b6c014',
name: 'name 4'
}
]
const userCounts= [
{ _id: '5efc2d84caa7964dcd843a7b', totalCount: 3 },
{ _id: '5efc41794664920022b6c014', totalCount: 1 }
]
let filtered=userCounts.map(item=>{
return districs.find(elemnt=>elemnt._id===item._id)
})
console.log(filtered)
here you go, you can modify it however you want.
try this if you want to use reduce and modify your array:
const result = districts.reduce((acc, curr) => {
const findUser = userCounts.filter(({ _id }) => _id === curr._id)
return [...acc, {...curr , user:findUser.length > 0 ? findUser[0].totalCount :0 }]
},[])
const districts = [
{
_id: '5efc41d74664920022b6c016',
name: 'name1'
},
{
_id: '5efc41a44664920022b6c015',
name: 'name2'
},
{
_id: '5efc2d84caa7964dcd843a7b',
name: 'name3'
},
{
_id: '5efc41794664920022b6c014',
name: 'name 4'
}
]
const userCounts = [
{ _id: '5efc2d84caa7964dcd843a7b', totalCount: 3 },
{ _id: '5efc41794664920022b6c014', totalCount: 1 }
]
const result = districts.reduce((acc, curr) => {
const findUser = userCounts.filter(({ _id }) => _id === curr._id)
return [...acc, {...curr , user:findUser.length > 0 ? findUser[0].totalCount :0 }]
},[])
console.log(result)

count occurrences of two keys in objects in array

I have the following array with objects and used the following code to creating a tally with the key "id":
var arr=[
{ id: 123,
title: "name1",
status: "FAILED"
},
{
id: 123,
title: "name1",
status: "PASSED"
},
{
id: 123,
title: "name1",
status: "PASSED"
},
{
id: 123,
title: "name1",
status: "PASSED"
},
{
id: 1234,
title: "name2",
status: "FAILED"
},
{
id: 1234,
title: "name2",
status: "PASSED"
}
];
const test =arr.reduce((tally, item) => {
if (!tally[item.id]) {
tally[item.id] = 1;
} else {
tally[item.id] = tally[item.id] + 1;
}
return tally;
}, {});
console.log(test);
Now what I want to do is to modify the tally to take in consideration the key status as well so the result will be somthing like:
[
{id:123, status:"PASSED", tally:3},
{id:123, status:"FAILED", tally:1},
{id:1234, status:"PASSED", tally:1},
{id:1234, status:"FAILED", tally:1}
]
Any idea? Thanks!
Just make the key item.id + item.status, then it's a simple assignment
const res = Object.values(arr.reduce((a, b) => {
a[b.id + b.status] = Object.assign(b, {tally: (a[b.id + b.status] || {tally: 0}).tally + 1});
return a;
}, {}));
console.log(res);
<script>
const arr=[
{ id: 123,
title: "name1",
status: "FAILED"
},
{
id: 123,
title: "name1",
status: "PASSED"
},
{
id: 123,
title: "name1",
status: "PASSED"
},
{
id: 123,
title: "name1",
status: "PASSED"
},
{
id: 1234,
title: "name2",
status: "FAILED"
},
{
id: 1234,
title: "name2",
status: "PASSED"
}
];
</script>
here you go
const test = arr.reduce((acc, item) => {
let found = acc.find(obj => obj.id === item.id && obj.status === item.status)
if (typeof found === "undefined") {
item.tally = 1
acc.push(item);
} else {
found.tally++;
}
return acc;
}, []);
You should group your items first using key that will contain both id and status:
const result = arr.reduce((acc, item) => {
const key = item.id + item.status;
acc[key] = acc[key] || { ...item, tally: 0 };
acc[key].tally++;
return acc;
}, {});
console.log( Object.values(result) );
Output:
[
{ id: 123, title: 'name1', status: 'FAILED', tally: 1 },
{ id: 123, title: 'name1', status: 'PASSED', tally: 3 },
{ id: 1234, title: 'name2', status: 'FAILED', tally: 1 },
{ id: 1234, title: 'name2', status: 'PASSED', tally: 1 },
]
Simply create a key with combination of id and status. And make a map using it. After that you can simply get the desired result from that.
Try the following:
var arr=[{id:123,title:"name1",status:"FAILED"},{id:123,title:"name1",status:"PASSED"},{id:123,title:"name1",status:"PASSED"},{id:123,title:"name1",status:"PASSED"},{id:1234,title:"name2",status:"FAILED"},{id:1234,title:"name2",status:"PASSED"}];
const map =arr.reduce((tally, item) => {
tally[item.id+"_"+item.status] = (tally[item.id+"_"+item.status] || 0) +1;
return tally;
}, {});
const result = Object.keys(map).map((a)=>{
var obj = {
id : a.split("_")[0],
status : a.split("_")[1],
tally : map[a]
};
return obj;
});
console.log(result);

Categories

Resources