What's the most efficent way to populate an a property of an array of objects with a larger array with data? - javascript

I have a small array of objects with properties, like so:
[
{
topicName: 'Clicks',
topic: 1,
dates: [ <PLACE VALUES HERE> ],
},
{
topicName: 'Cost',
topic: 2,
dates: [ <PLACE VALUES HERE> ],
},
];
Then I have a large array of objects that I wish to extract some of the properties from in to the above dates array.
Here's what the data I wish to extract from:
[
{
"date": "2014-02-01",
"device": "Computer",
"match-type": "NA",
"clicks": 66,
"revenue": 1037,
"conversions": 2,
"cost": 284.35,
"impressions": 5330,
"ROI": 3.64691401441885
},
{
"date": "2014-02-01",
"device": "Tablet",
"match-type": "NA",
"clicks": 38,
"revenue": 587,
"conversions": 2,
"cost": 194.01000000000005,
"impressions": 1934,
"ROI": 3.025617236224936
},
{
"date": "2014-02-02",
"device": "Tablet",
"match-type": "NA",
"clicks": 40,
"revenue": 587,
"conversions": 2,
"cost": 190,
"impressions": 1934,
"ROI": 3.025617236224936
},
]
Now I need the data from all of the members of the last array and insert that releveant data for the particular object in the first array (totalling where necessary), like so:
[
{
topicName: 'Clicks',
topic: 1,
dates: [
{
date: '2014-02-01',
value: 104
},
{
date: '2014-02-02',
value: 40
}
],
},
{
topicName: 'Cost',
topic: 2,
dates: [
{
date: '2014-02-01',
value: 284,3519401
},
{
date: '2014-02-02',
value: 190
}
],
},
];
The target is the latest version of Chrome and I'm using Webpack with Babel so all the latest stuff is available.
Assuming the last dataset can be pretty large, what's the most efficient way to go about this?
[EDIT]
This is what I've come up with so far:
const dataAdapter = rawData => {
const topics = ['clicks', 'revenue', 'cost', 'roi'];
const topicsData = topics.map((topic, index) => {
const thisTopic = {};
thisTopic.topicName = topic;
thisTopic.topic = index;
thisTopic.dates = [];
return thisTopic;
});
const convertedData = topicsData.map(topicData => {
const thisTopic = topicData;
const map = new Map();
rawData.forEach(elem => {
map.set(elem.date, (map.get(elem.date) || 0) + elem[[thisTopic.topicName]]);
});
thisTopic.dates = Array.from(map);
return thisTopic;
});
return convertedData;
};
Thanks,
/J

You could take an object as reference to the wanted keys and date. Then iterate data and check if a reference to a result set exists. If not, create a new result set.
var result = [{ topicName: 'Clicks', topic: 1, dates: [], }, { topicName: 'Cost', topic: 2, dates: [], }],
data = [{ date: "2014-02-01", device: "Computer", "match-type": "NA", clicks: 66, revenue: 1037, conversions: 2, cost: 284.35, impressions: 5330, ROI: 3.64691401441885 }, { date: "2014-02-01", device: "Tablet", "match-type": "NA", clicks: 38, revenue: 587, conversions: 2, cost: 194.01000000000005, impressions: 1934, ROI: 3.025617236224936 }, { date: "2014-02-02", device: "Tablet", "match-type": "NA", clicks: 40, revenue: 587, conversions: 2, cost: 190, impressions: 1934, ROI: 3.025617236224936 }],
hash = { clicks: { _: result[0].dates }, cost: { _: result[1].dates }, };
data.forEach(function (o) {
['clicks', 'cost'].forEach(function (k) {
if (!hash[k][o.date]) {
hash[k][o.date] = { date: o.date, value: o[k] };
hash[k]._.push(hash[k][o.date]);
return;
}
hash[k][o.date].value += o[k];
});
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Assuming your data is in data variable and topics are in topics variable. This solution uses only javascript builtin objects.
const getPropDateMap = (obj, prop) => obj
.reduce((accObj, item) => {
return Object.assign(accObj, {
[item.date]: item.clicks + (accObj[item.date] || 0)
})
}, {})
topics.forEach(topic => {
topic.dates = Object
.entries(getPropDateMap(data, topic.topicName.toLowerCase()))
.map(entry => ({date: entry[0], value: entry[1]}))
})

Related

Javascript to manipulate object structure

I have a javascript object with the following schema:
[{
face:"n",
values:[
{time:"15:00",value:5}
{time:"15:02",value:6}
]
},{
face:"e",
values:[
{time:"15:01",value:7}
{time:"15:02",value:8}
]
},{
face:"s",
values:[
{time:"15:01",value:7}
{time:"15:02",value:8}
]
},{
face:"w",
values:[
{time:"15:01",value:7}
{time:"15:02",value:8}
]
}]
How to convert it to the following structure:
[
{time:"15:00","n":5,"e":null,"s":null,"w":null},
{time:"15:01","n":null,"e":7,"s":7,"w":7},
{time:"15:02","n":6,"e":8,"s":8,"w":8},
]
The number of faces will be fixed (north, east, south, west)
It is possible that some timestamps are missing. In that case we need to fill the value with 'null' (see example above).
You can easily achieve the result using Map, reduce and forEach
with this approach the ordering is not particular, If you want the exact time ordering then you can sort it using the following custorm sort comparator function
result.sort((a, b) => +a.time.match(/\d+/g).join("") - b.time.match(/\d+/g).join(""))
const arr = [
{
face: "n",
values: [
{ time: "15:00", value: 5 },
{ time: "15:02", value: 6 },
],
},
{
face: "e",
values: [
{ time: "15:01", value: 7 },
{ time: "15:02", value: 8 },
],
},
{
face: "s",
values: [
{ time: "15:01", value: 7 },
{ time: "15:02", value: 8 },
],
},
{
face: "w",
values: [
{ time: "15:01", value: 7 },
{ time: "15:02", value: 8 },
],
},
];
const map = new Map();
const result = [
...arr.reduce((acc, { face, values }) => {
values.forEach(({ time, value }) => {
if (!acc.has(time))
acc.set(time, { time, n: null, e: null, s: null, w: null });
acc.get(time)[face] = value;
});
return acc;
}, map)
.values(),
];
console.log(result);
/* This is not a part of answer. It is just to give the output full height. So IGNORE IT */
.as-console-wrapper { max-height: 100% !important; top: 0; }
Because you haven't added what you tried so far (which is kinda useless for this task, IMHO), I will just answer in form of how I would tackle this task.
Locate your unique value in your expected output: time.
Loop through your array, and create an object with keys based on time. Save the properties name and each of the four faces, by first creating null values for all faces, and then filling it out with one value at time as a new timestamp appears in the array.
Here is how the whole object will look like:
{
"15:00": {time:"15:00","n":5,"e":null,"s":null,"w":null},
"15:01": {time:"15:01","n":null,"e":7,"s":7,"w":7},
"15:02": {time:"15:02","n":6,"e":8,"s":8,"w":8
}
Loop through the object—with for... in, [edit] or by simply using Object.values—to create an array out of it.
You can probably use some smart Array.reduce() functionality to minimize the code.
let old_array = [{
face: "n",
values: [
{ time: "15:00", value: 5 },
{ time: "15:02", value: 6 }
]
}, {
face: "e",
values: [
{ time: "15:01", value: 7 },
{ time: "15:02", value: 8 }
]
}, {
face: "s",
values: [
{ time: "15:01", value: 7 },
{ time: "15:02", value: 8 }
]
}, {
face: "w",
values: [
{ time: "15:01", value: 7 },
{ time: "15:02", value: 8 }
]
}];
let new_array = []
let times = {}
let faces = {"n": "north", "e": "east", "s": "south", "w": "west"}
old_array.forEach((obj) => {
obj.values.forEach((val) => {
if(val.time in times)
times[val.time][faces[obj.face]] = val.value
else {
let newT = {time: val.time, "north": null, "east": null, "south": null, "west": null}
newT[faces[obj.face]] = val.value
times[val.time] = newT
new_array.push(newT)
}
})
})
new_array.sort((a,b)=>a.time < b.time ? -1 : (a.time > b.time ? 1 : 0))
console.log(new_array)
// Expected output
// [
// { time: '15:00', north: 5, east: null, south: null, west: null },
// { time: '15:01', north: null, east: 7, south: 7, west: 7 },
// { time: '15:02', north: 6, east: 8, south: 8, west: 8 }
// ]

Change objects structure

I have an array of objects:
const res = [
{
KIND_ID: 2229,
NAME: "Group",
SKU_ID: 311,
ARTICLE_NAME: "Product one",
WEEK: 202027,
FORECAST: 81928.37,
PROMO: 0,
SALES: 92848,
SAFETY_STOCK: 57704.79,
STORES_COUNT: 132,
ADD_FCST: null
},
{
KIND_ID: 2229,
NAME: "Group",
SKU_ID: 311,
ARTICLE_NAME: "Product one",
WEEK: 202028,
FORECAST: 84278.85,
PROMO: 0,
SALES: null,
SAFETY_STOCK: 64000.39,
STORES_COUNT: 144,
ADD_FCST: null
},
{
KIND_ID: 2229,
NAME: "Group",
SKU_ID: 316,
ARTICLE_NAME: "Product two",
WEEK: 202027,
FORECAST: 89112.97,
PROMO: 0,
SALES: 98007,
SAFETY_STOCK: 59509.31,
STORES_COUNT: 142,
ADD_FCST: null
},
{
KIND_ID: 2229,
NAME: "Group",
SKU_ID: 316,
ARTICLE_NAME: "Product two",
WEEK: 202028,
FORECAST: 85129.4,
PROMO: 0,
SALES: null,
SAFETY_STOCK: 63409.61,
STORES_COUNT: 144,
ADD_FCST: null
}
];
I want to group some fields in WEEKS, e.g:
const expected = [
{
KIND_ID: 2229,
NAME: "Group",
SKU_ID: 311,
ARTICLE_NAME: "Product one",
FORECAST: [{ 202026: 97555.64 }, { 202027: 98336.45 }],
PROMO: [{ 202026: 0 }, { 202027: 0 }],
SALES: [{ 202026: 95911.77 }, { 202027: null }],
SAFETY_STOCK: [{ 202026: 63622.28 }, { 202027: 72852.62 }],
STORES_COUNT: [{ 202026: 135 }, { 202027: 143 }],
ADD_FCST: [{ 202026: null }, { 202027: null }]
},
{
KIND_ID: 2229,
NAME: "Group",
SKU_ID: 316,
ARTICLE_NAME: "Product two",
FORECAST: [{ 202026: 104125.69 }, { 202027: 101147.07 }],
PROMO: [{ 202026: 0 }, { 202027: 0 }],
SALES: [{ 202026: 102281 }, { 202027: null }],
SAFETY_STOCK: [{ 202026: 53709.55 }, { 202027: 60675.26 }],
STORES_COUNT: [{ 202026: 143 }, { 202027: 144 }],
ADD_FCST: [{ 202026: null }, { 202027: null }]
}
];
If it helps i have array of weeks and values need to be grouped:
const weeks = [202027, 202028];
const keys = ['FORECAST','PROMO','SALES','SAFETY_STOCK','STORES_COUNT','ADD_FCST'];
I tried to solve with reduce and underscore method groupBy but this not helped. How to group this res array to expected?
Dummy text, because: It looks like your post is mostly code; please add some more details. But that's all what i want to tell
I tried to solve with reduce
That's what I'd use, although there is a few steps involved as this isn't a classic grouping schematic.
Below is an example.
const res=[{KIND_ID:2229,NAME:"Group",SKU_ID:311,ARTICLE_NAME:"Product one",WEEK:202027,FORECAST:81928.37,PROMO:0,SALES:92848,SAFETY_STOCK:57704.79,STORES_COUNT:132,ADD_FCST:null},{KIND_ID:2229,NAME:"Group",SKU_ID:311,ARTICLE_NAME:"Product one",WEEK:202028,FORECAST:84278.85,PROMO:0,SALES:null,SAFETY_STOCK:64000.39,STORES_COUNT:144,ADD_FCST:null},{KIND_ID:2229,NAME:"Group",SKU_ID:316,ARTICLE_NAME:"Product two",WEEK:202027,FORECAST:89112.97,PROMO:0,SALES:98007,SAFETY_STOCK:59509.31,STORES_COUNT:142,ADD_FCST:null},{KIND_ID:2229,NAME:"Group",SKU_ID:316,ARTICLE_NAME:"Product two",WEEK:202028,FORECAST:85129.4,PROMO:0,SALES:null,SAFETY_STOCK:63409.61,STORES_COUNT:144,ADD_FCST:null}];
const grpFields = ['FORECAST', 'PROMO', 'SALES', 'SAFETY_STOCK',
'STORES_COUNT', 'ADD_FCST'];
const o = res.reduce((a, v) => {
const {KIND_ID, NAME, SKU_ID, ARTICLE_NAME} = v;
let f = a.find(f => f.SKU_ID === v.SKU_ID);
if (!f) {
f = {KIND_ID, NAME, SKU_ID, ARTICLE_NAME};
grpFields.forEach(k => f[k] = []);
a.push(f);
}
grpFields.forEach(k => f[k].push({[v.WEEK]: v[k]}));
return a;
},[]);
console.log(o);
To make this a generic function, you will need to pass a few parameters.
Below is an example.
arr = The array your wanting to group
grpFields = The fields that you want the grouping applied to
grpValue = The field value your grouping
keyField = What field we are grouping on
stdFields = Other fields you want as part of the result
const res=[{KIND_ID:2229,NAME:"Group",SKU_ID:311,ARTICLE_NAME:"Product one",WEEK:202027,FORECAST:81928.37,PROMO:0,SALES:92848,SAFETY_STOCK:57704.79,STORES_COUNT:132,ADD_FCST:null},{KIND_ID:2229,NAME:"Group",SKU_ID:311,ARTICLE_NAME:"Product one",WEEK:202028,FORECAST:84278.85,PROMO:0,SALES:null,SAFETY_STOCK:64000.39,STORES_COUNT:144,ADD_FCST:null},{KIND_ID:2229,NAME:"Group",SKU_ID:316,ARTICLE_NAME:"Product two",WEEK:202027,FORECAST:89112.97,PROMO:0,SALES:98007,SAFETY_STOCK:59509.31,STORES_COUNT:142,ADD_FCST:null},{KIND_ID:2229,NAME:"Group",SKU_ID:316,ARTICLE_NAME:"Product two",WEEK:202028,FORECAST:85129.4,PROMO:0,SALES:null,SAFETY_STOCK:63409.61,STORES_COUNT:144,ADD_FCST:null}];
function groupData(arr, grpFields, grpValue, keyField, stdFields) {
return arr.reduce((a, v) => {
let f = a.find(f => f[keyField] === v[keyField]);
if (!f) {
f = Object.fromEntries(stdFields.map(k => [k, v[k]]));
grpFields.forEach(k => f[k] = []);
a.push(f);
}
grpFields.forEach(k => f[k].push({[v[grpValue]]: v[k]}));
return a;
},[]);
}
console.log(
groupData(
res,
['FORECAST', 'PROMO', 'SALES', 'SAFETY_STOCK','STORES_COUNT', 'ADD_FCST'],
'WEEK',
'SKU_ID',
['KIND_ID', 'NAME', 'SKU_ID', 'ARTICLE_NAME']
)
);

Extracting objects out of arrays

I want to map from this:
companies: {
apples: {
Q7: {
price: 1,
},
Q6: {
price: 1,
},
peaches: {
Q7: {
price: 1,
},
Q6: {
price: 1,
},
},
};
to this:
{ "companies": {
"apples": [
{
"name": "Q7",
"price": 1
},{
"name": "Q6",
"price": 1
}
],
"peaches": [
{
"name": "Q7",
"price": 1
},{
"name": "Q6",
"price": 1
}
]
}
}
How I am trying to achieve this:
I have a selector which gives me the companies object and then I map over it and assemble my object but I don't get it quite right.
This is my function:
const weaponProducts = Object.entries(getCompanies(state)).map(([companyType, companies]) => {
const prod = Object.entries(companies).map(([key, companies]) => {
return {
name: key,
price: companies.price
}
});
return {
[companyType]: prod
};
});
getCompanies(state) returns the following object:
{
"companies": {
"apples": {
"Q7": {
"price": 1
},
"Q6": {
"price": 1
}
},
"peaches": {
"Q7": {
"price": 1
},
"Q6": {
"price": 1
}
}
}
}
The result of the function is the following. But as explained I want it to look like the second code section of my post.
[
{
"apples": [
{
"name": "Q7",
"price": 1
},
{
"name": "Q6",
"price": 1
},
]
},
{
"peaches": [
{
"name": "Q7",
"price": 1
},
{
"name": "Q6",
"price": 1
},
]
}
]
since your desired output is an object, not an array, you should use reduce instead of map:
let companies = {
apples: {
Q7: {
price: 1,
},
Q6: {
price: 1,
},
},
peaches: {
Q7: {
price: 1,
},
Q6: {
price: 1,
},
},
}
let fruit = Object.keys(companies)
let output = fruit.reduce((output, currentFruit) => {
output[currentFruit] = Object.keys(companies[currentFruit]).map(q => {
return { name: q, price: companies[currentFruit][q].price }
})
return output
}, {});
console.log(output);
(I think there was a syntax error in your companies object, I corrected in the snippet)
You can also take entries and then map the objects accordingly.
var companies = { apples: { Q7: { price: 1, }, Q6: { price: 1, }, }, peaches: { Q7: { price: 1, }, Q6: { price: 1, } }};
const result = (inputObj) =>
Object.fromEntries(
Object.entries(inputObj).map(([key, obj]) => [
key,
Object.entries(obj).map(([name, val]) => ({ name, ...val })),
])
);
console.log(result(companies));
If you're down to try something new, here's a different way to express the desired transformation using a library I authored.
const x = { companies: { apples: { Q7: { price: 1, }, Q6: { price: 1, }, }, peaches: { Q7: { price: 1, }, Q6: { price: 1, }, }, } }
const { pipe, fork, map, tap, get } = rubico
const y = map(map(pipe([
Object.entries,
map(fork({
name: get(0),
price: get([1, 'price']),
})),
])))(x)
console.log(JSON.stringify(y, null, 2))
<script src="https://unpkg.com/rubico/index.js"></script>

Javascript: create a deeply nested object in javascript from another object

Javascript: How to dynamically create a deeply nested object from an array of objects?
I could achieve one level of separation, but the code has got quite complicated and am not able to figure out how to achieve this for 2nd level.
Actual:
[{
brandId: 1,
spec_desc: "engines",
av: 3000
tv: 1000,
brandName: "bmw",
id: 1,
group: "cars",
cost: 20000.00,
currency: "USD",
desc: "manufacturing costs"
},
{
brandId: 1,
spec_desc: "brakes",
av: 1000,
tv: 2000,
brandName: "bmw",
id: 1,
....
},
{
brandId: 2,
spec_desc: "engines",
av: 1800,
tv: 2500,
brandName: "audi",
id: 2
....
}
]
Expected:
[{
group: "cars",
id: 1,
brands: [{
brandId: 1,
brandName: "BMW",
specs: {
power: [{
spec_desc: "engines",
av: 3000,
tv: 1000
},
{
spec_desc: "brakes",
av: 1000,
tv: 2000
}
],
cost: {
desc: "manufacturing costs",
value: 20000.00,
currency: "USD"
}
}
},
{
brandId: 2,
brandName: "audi",
specs: {
power: [
...
],
}
}
]
},
group: "bikes",
id: 2,
brands: [
....
]
]
Here is what I have tried, but able to obtain grouping only till brandName i-e one level.
function genrows(groups, groupKey) {
return _.toPairs(groups).map(([key, units]) => ({
[groupKey]: key,
units
}))
}
function gengroups(arr, iteratee, key) {
const grouped = _.groupBy(arr, iteratee)
return genrows(grouped, key)
}
function grouparray(units, props) {
let result = [{
units
}]
props.forEach((prop, i) => {
const key = prop
const iteratee = prop.iteratee || prop
result = _.flatten(
result.map(row => {
return gengroups(row.units, iteratee, key).map(group =>
// {...row, ...{ [key]: group[key], units: group.units }}
({ ...row,
[key]: group[key],
units: group.units
}),
)
}),
)
})
return _.flatten(result)
}
const groups = ['brandName', 'id'] //group by key names
// it fetches out these group tags to generate keys,
const desired = grouparray(actual, groups);
Can anyone help me work out how to achieve this dynamically? If you've got this far thanks very much for taking the time to read even if you can't help.
PS: Let me know for further clarifications, my result object & also have used lodash functions.
You could take a classic approach by storing the last group, where an id is found and group the brands with this object.
var data = [{ brandId: 1, spec_desc: "engines", av: 3000, tv: 1000, brandName: "bmw", id: 1, group: "cars", cost: 20000.00, currency: "USD", desc: "manufacturing costs" }, { brandId: 1, spec_desc: "brakes", av: 1000, tv: 2000, brandName: "bmw" }, { brandId: 2, spec_desc: "engines", av: 1800, tv: 2500, brandName: "audi" }],
lastGroup,
result = data.reduce((r, { brandId, spec_desc, av, tv, brandName, id, group, cost: value, currency, desc }) => {
if (id !== undefined) r.push(lastGroup = { group, id, brands: [] });
var brand = lastGroup.brands.find(q => q.brandId === brandId);
if (!brand) lastGroup.brands.push(brand = { brandId, brandName, specs: { power: [], cost: { desc, value, currency } } });
brand.specs.power.push({ spec_desc, av, tv });
return r;
}, []);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

ES6 Nested Grouping with Sum

I have an array like this:
[{
id: 1,
amount: 10,
date: '21/01/2017'
},{
id: 1,
amount: 10,
date: '21/01/2017'
},{
id: 1,
amount: 30,
date: '22/01/2017'
},{
id: 2,
amount: 10,
date: '21/01/2017'
},]
And I would like this to output like:
{
'21/01/2017': {
1: {
amount: 20
},
2: {
amount: 10
}
},
'22/01/2017': {
1: {
amount: 30
}
}
}
Essentially grouping by data, nested grouping by id, whilst summing the relevant amounts.
So far I have tried using reduce, and have looked at lodash functions but have been unsuccessful. Reduce makes it easy to group by and sum by one prop, but I cannot find an elegant way to create the second level. I have created the a sandbox to demonstrate:
https://codesandbox.io/s/woj9xz6nq5
const dataToConsolidate = [{
id: 1,
amount: 10,
date: '21/01/2017'
}, {
id: 1,
amount: 10,
date: '21/01/2017'
}, {
id: 1,
amount: 30,
date: '22/01/2017'
}, {
id: 2,
amount: 10,
date: '21/01/2017'
},]
export const consolidate = (data) => {
const result = data.reduce(function (res, obj) {
(!(obj.date in res)) ?
res.__array.push(res[obj.date] = obj) :
res[obj.date].amount += obj.amount;
return res;
}, { __array: [] });
return result;
};
console.log(consolidate(dataToConsolidate))
You could take the object as hash table and add the properties with a default style.
var array = [{ id: 1, amount: 10, date: '21/01/2017' }, { id: 1, amount: 10, date: '21/01/2017' }, { id: 1, amount: 30, date: '22/01/2017' }, { id: 2, amount: 10, date: '21/01/2017' }],
result = {};
array.forEach(function (o) {
result[o.date] = result[o.date] || {};
result[o.date][o.id] = result[o.date][o.id] || { amount: 0 };
result[o.date][o.id].amount += o.amount;
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Here's a relatively ES6-y solution using reduce:
const initial = [{ id: 1, amount: 10, date: '21/01/2017' }, { id: 1, amount: 10, date: '21/01/2017' }, { id: 1, amount: 30, date: '22/01/2017' }, { id: 2, amount: 10, date: '21/01/2017' }];
const parse = obj => obj.reduce((final, { date, id, amount }) => {
let group = final[date] = final[date] || {};
group[id] = group[id] || { amount: 0 };
group[id].amount += amount;
return final;
}, {});
const final = parse(initial);
console.log(final);
You'll want to add appropriate logic to handle missing/erroneous date, id, or amount keys.
As a fan of the library Ramda (disclaimer: I'm one of the authors), I might well use it to make everything a bit more explicit:
const {pipe, groupBy, prop, map, pluck, sum} = R
const data = [
{"amount": 10, "date": "21/01/2017", "id": 1},
{"amount": 10, "date": "21/01/2017", "id": 1},
{"amount": 30, "date": "22/01/2017", "id": 1},
{"amount": 10, "date": "21/01/2017", "id": 2}
]
const consolidate = pipe(
groupBy(prop('date')),
map(groupBy(prop('id'))),
map(map(pluck('amount'))),
map(map(sum))
)
console.log(consolidate(data))
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
Of course using a library just to solve this problem is simply overkill, when something like the solution from #NinaSholz does just fine. But if you find several places where it could help, it might be worth looking into something like that.
you can do it thru _.groupBy:
const res = _.chain(data)
.groupBy('date')
.mapValues(dateObj => _.chain(dateObj)
.groupBy('id')
.mapValues(idObj => ({ amount: _.sumBy(idObj, 'amount') }))
.value()
)
.value();

Categories