Reduce array of objects without using .push() - javascript

I have this array of objects:
[
{
user: 'User_1',
date: 1603926000000,
count: 3,
},
{
user: 'User_2',
date: 1603926000000,
count: 10,
},
{
user: 'User_2',
date: 1604876400000,
count: 1,
},
]
I reduce it with this function:
const reducedDataByDate = dataByDate.reduce((acc, d) => {
const foundUser = acc.find((a) => a.user === d.user)
const value = { date: formatDate(d.date), count: d.count }
if (!foundUser) {
acc.push({ user: d.user, data: [value] })
} else {
foundUser.data.push(value)
}
return acc
}, [])
with this outcome:
[
{
user: 'User_1',
data: [
{
date: '2020-10-29',
count: 10,
},
{
date: '2020-11-09',
count: 1,
},
],
},
{
user: 'User_2',
data: [
{
date: '2020-10-29',
count: 3,
},
],
},
]
Ideally, I would like get rid of pushing values to original acc and foundUser array but have little idea how to go about that. Any input is much appreciated!

You could collect the data with a Map and get the wanted format from it.
const
data = [{ user: 'User_1', date: 1603926000000, count: 3 }, { user: 'User_2', date: 1603926000000, count: 10 }, { user: 'User_2', date: 1604876400000, count: 1 }],
result = Array.from(
data.reduce(
(m, { user, ...o }) => m.set(user, [...(m.get(user) || []), o]),
new Map
),
([user, data]) => ({ user, data })
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

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 };
});

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

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;
}
});

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));

React How to add new dynamic key to existing state?

I have getting the data from database as an array.
So now I'm getting array like this:
orders:[
{
_id:1,
name: honda,
}
{
_id:2,
name: suzuki,
}
{
_id:3,
name: audi,
}
]
So my question is how can I attach new key value to the array, so It needs to look like this:
orders:[
{
_id:1,
name: honda,
opened:true,
}
{
_id:2,
name: suzuki,
opened:true,
}
{
_id:3,
name: audi,
opened:true,
}
]
For now I'm trying with this code, but this doesn't work:
getOrders(orders).then(response => {
response.map(itm=>{
const ordersData=[...itm]
const opened={opened:true}
this.setState({
openedOrders: [ordersData,opened]
})
})
})
openedOrders is new state object that I create.
What is best solution for this?
Thanks
Your map should look like this. (Note the return statement in map function)
orders.map(item=> {
return {...item, opened:true}
})
So your function could look like
getOrders(orders).then(response => {
let openedOrders = orders.map(item=> {
return {...item, opened:true}
})
this.setState({
openedOrders
})
})
Assuming response contains the first array in your OP:
getOrders(orders).then(response => {
const openedOrders = response.map(order => ({ ...order, open: true}))
this.setState({ openedOrders } )
})
response.map(order => ({ ...order, open: true}) adds a key open with the value true to every order in the array.
To add dynamic keys to a object in javascript we use [].
var x = [{ _id : 1, name: Suzuki}];
x[0]['opened'] = true;
console.log(x);
// [{ _id : 1, name: Suzuki, opened: true}];
Use foreach() to loop through all the orders in the array and add the desired property for each order.
let orders = [{
_id: 1,
name: 'honda',
}, {
_id: 2,
name: 'suzuki',
}, {
_id: 3,
name: 'audi',
}]
orders.forEach(o => o.opened = true)
console.log(orders)
You could add a new property to the objects.
var orders = [{ _id: 1, name: 'honda' }, { _id: 2, name: 'suzuki' }, { _id: 3, name: 'audi' }],
additionalProp = { opened: true };
orders.forEach(o => Object.assign(o, additionalProp));
console.log(orders);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Or map a new array without mutating the original objects.
var orders = [{ _id: 1, name: 'honda' }, { _id: 2, name: 'suzuki' }, { _id: 3, name: 'audi' }],
additionalProp = { opened: true },
result = orders.map(o => Object.assign({}, o, additionalProp));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Transform the data

I have the following data structure:
const data = [
{
name: 'ABC',
salesData: [
{
timestamp: '2017-09-01',
value: 10
},
{
timestamp: '2017-09-02',
value: 2
}
]
},
{
name: 'DEF',
salesData: [
{
timestamp: '2017-09-01',
value: 8
},
{
timestamp: '2017-09-02',
value: 3
}
]
}
];
I would like to transform this to:
[
{
name: 'ABC',
'2017-09-01': 10,
'2017-09-02': 2
},
{
name: 'CDE',
'2017-09-01': 8,
'2017-09-02': 3
}
]
I'm trying to use Underscore's Chain and Map which I'm getting confused. So far I have the following, not sure how do I write the convertedSalesData to transform as per the need:
_.map(data, function(item) {
let name = item.name;
let salesData = item.salesData;
let convertedSalesData = ?
})
With ES6 you can use spread syntax ... to get this result.
const data = [{"name":"ABC","salesData":[{"timestamp":"2017-09-01","value":10},{"timestamp":"2017-09-02","value":2}]},{"name":"DEF","salesData":[{"timestamp":"2017-09-01","value":8},{"timestamp":"2017-09-02","value":3}]}]
var result = data.map(function({name, salesData}) {
return {name, ...Object.assign({}, ...salesData.map(({timestamp, value}) => ({[timestamp]: value})))}
})
console.log(result)
const data = [{
name: 'ABC',
salesData: [{
timestamp: '2017-09-01',
value: 10
},
{
timestamp: '2017-09-02',
value: 2
}
]
},
{
name: 'DEF',
salesData: [{
timestamp: '2017-09-01',
value: 8
},
{
timestamp: '2017-09-02',
value: 3
}
]
}
];
var res = data.map(function(a) {
var obj = {
name: a.name
};
a.salesData.forEach(function(x) {
obj[x.timestamp] = x.value;
})
return obj;
})
console.log(res);
Similar to #Nenad Vracar. I perfer to use 'reduce':
data.map(({ name, salesData }) => ({
name,
...salesData.reduce(
(record, { timestamp, value }) => {
record[timestamp] = value
return record
},
Object.create(null)
)
}))

Categories

Resources