Reputation: 646
I have an Object that looks like this:
var dataSource = [{
date: new Date(1994, 2, 2),
name: "a",
l: 24.00,
h: 25.00,
o: 25.00,
c: 24.875
}, {
date: new Date(1994, 2, 2),
name: "a",
l: 23.625,
h: 25.125,
o: 24.00,
c: 24.875
}, {
date: new Date(1994, 2, 3),
name: "a",
l: 26.25,
h: 28.25,
o: 26.75,
c: 27.00
}, {
date: new Date(1994, 2, 4),
name: "c",
l: 26.50,
h: 27.875,
o: 26.875,
c: 27.25
}, {
and so on... I want to combine entries by their date, meaning if two datapoints have the same date and name, I want to add them together so the output would be:
var dataSource = [{
date: new Date(1994, 2, 2),
name: "a",
l: 47.625,
h: 50.125,
o: 49.00,
c: 49.75
}, {
date: new Date(1994, 2, 3),
name: "a",
l: 26.25,
h: 28.25,
o: 26.75,
c: 27.00
}, {
date: new Date(1994, 2, 4),
name: "c",
l: 26.50,
h: 27.875,
o: 26.875,
c: 27.25
}, {
Right now the best way I can think of doing this would be a for loop that runs until the size of the object doesnt change any more. Is there a better way of doing this, possibly a jquery function similar to grep that could do this?
Upvotes: 0
Views: 162
Reputation: 22265
this way
const data =
[ { date: new Date(1994, 2, 2), name: "a"
, l: 24.00, h: 25.00, o: 25.00, c: 24.875
}
, { date: new Date(1994, 2, 2), name: "a"
, l: 23.625, h: 25.125, o: 24.00, c: 24.875
}
, { date: new Date(1994, 2, 3), name: "a"
, l: 26.25, h: 28.25, o: 26.75, c: 27.00
}
, { date: new Date(1994, 2, 4), name: "c"
, l: 26.50, h: 27.875, o: 26.875, c: 27.25
}
]
const Result = data.reduce((acc,c)=>
{
let same = acc.find(x=>x.date.getTime()===c.date.getTime()
&& x.name===c.name)
if(!same)
acc.push({...c})
else
{
same.l += c.l
same.h += c.h
same.o += c.o
same.c += c.c
}
return acc
}, [])
console.log( Result )
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 0
Reputation: 12911
You can use a reduce()
call grouping elements by a compound key made of the the date concatenated with the name (o.date.valueOf() + o.name
), summing the relevant keys and then calling Object.values()
on the result to return an array of the merged objects.
const dataSource = [{ date: new Date(1994, 2, 2), name: "a", l: 24.00, h: 25.00, o: 25.00, c: 24.875 }, { date: new Date(1994, 2, 2), name: "a", l: 23.625, h: 25.125, o: 24.00, c: 24.875 }, { date: new Date(1994, 2, 3), name: "a", l: 26.25, h: 28.25, o: 26.75, c: 27.00 }, { date: new Date(1994, 2, 4), name: "c", l: 26.50, h: 27.875, o: 26.875, c: 27.25 }];
const
sumKeys = (a, b) => ['l', 'h', 'o', 'c'].forEach(k => a[k] += b[k]),
grouped = Object.values(
dataSource.reduce((a, o) => {
const entry = (a[o.date.valueOf() + o.name] ??= { name: o.name, date: o.date.valueOf(), l: 0, h: 0, o: 0, c: 0 });
sumKeys(entry, o);
return a;
}, {}));
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
or if you need to avoid logical nullish assignment (??=) for compatibility...
const dataSource = [{ date: new Date(1994, 2, 2), name: "a", l: 24.00, h: 25.00, o: 25.00, c: 24.875 }, { date: new Date(1994, 2, 2), name: "a", l: 23.625, h: 25.125, o: 24.00, c: 24.875 }, { date: new Date(1994, 2, 3), name: "a", l: 26.25, h: 28.25, o: 26.75, c: 27.00 }, { date: new Date(1994, 2, 4), name: "c", l: 26.50, h: 27.875, o: 26.875, c: 27.25 }];
const
sumKeys = (a, b) => ['l', 'h', 'o', 'c'].forEach(k => a[k] += b[k]),
grouped = Object.values(
dataSource.reduce((a, o) => {
const entry = (a[o.date.valueOf() + o.name] = a[o.date.valueOf() + o.name] || { name: o.name, date: o.date.valueOf(), l: 0, h: 0, o: 0, c: 0 });
sumKeys(entry, o);
return a;
}, {}));
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 1
Reputation: 483
let arr = dataSource.reduce((cur, next) => {
const flag = cur.some(ele => {
return ele.date.valueOf() === next.date.valueOf() && ele.name === next.name
})
if(!flag) {
cur.push(next)
}
return cur;
}, [])
console.log(arr)
Upvotes: 0
Reputation: 4592
you can track the date and name in a mapper first
var dataSource = [{
date: new Date(1994, 2, 2),
name: "a",
l: 24.00,
h: 25.00,
o: 25.00,
c: 24.875
}, {
date: new Date(1994, 2, 2),
name: "a",
l: 23.625,
h: 25.125,
o: 24.00,
c: 24.875
}, {
date: new Date(1994, 2, 3),
name: "a",
l: 26.25,
h: 28.25,
o: 26.75,
c: 27.00
}, {
date: new Date(1994, 2, 4),
name: "c",
l: 26.50,
h: 27.875,
o: 26.875,
c: 27.25
}];
const mapper = dataSource.reduce((acc, cur) => {
acc[cur.date] = acc[cur.date] || {};
acc[cur.date][cur.name] = acc[cur.date][cur.name] || {};
["l", "h", "o", "c"].forEach(k => {
acc[cur.date][cur.name][k] = (acc[cur.date][cur.name][k] || 0) + cur[k];
});
return acc;
}, {});
const result = [];
Object.keys(mapper).forEach(d => {
Object.keys(mapper[d]).forEach(name => {
const item = mapper[d][name];
result.push({
date: d,
name,
l: item.l,
h: item.h,
o: item.o,
c: item.c,
});
});
});
console.log(result);
Upvotes: 0