nest array of objects [closed] - javascript

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 days ago.
Improve this question
I have an array of objects
const data = [
{
"name": "john",
"savings": 900,
"firm": "chase",
"advisor": "holly"
},
{
"name": "carol",
"savings": 500,
"checking": 600,
"firm": "chase",
"advisor": "mark"
},
{
"name": "sarah",
"savings": 500,
"checking": 300,
"firm": "chase",
"advisor": "holly"
},
{
"name": "toby",
"savings": 500,
"checking": 300,
"firm": "chase",
"advisor": "mark"
},
{
"name": "casey",
"savings": 500,
"checking": 200,
"firm": "citiBank",
"advisor": "cindy"
},
{
"name": "bruce",
"checking": 200,
"firm": "chase",
"advisor": "holly"
},
{
"name": "jim",
"checking": 200,
"firm": "chase",
"advisor": "holly"
},
{
"name": "nich",
"firm": "chase",
"advisor": "mark"
}
]
Sample code
const getFirms = (data) => {
const firms = [];
return firms;
};
When we console.log(getFirms(data)) we should get the below output
[
{
name: 'chase',
advisors: [
{
name: 'mark',
clients: [
{ name: 'carol', savings: 500, checking: 600 },
{ name: 'toby', savings: 500, checking: 300 },
{ name: 'nich' }
]
},
{
name: 'holly',
clients: [
{ name: 'john', savings: 900 },
{ name: 'jim', checking: 200 },
{ name: 'bruce', checking: 200 },
{ name: 'sarah', savings: 500, checking: 300 }
]
}
]
},
{
name: 'citiBank',
advisors: [
{
name: 'cindy',
clients: [ { name: 'casey', savings: 500, checking: 200 } ]
},
{ name: 'bob', clients: null }
]
},
{ name: 'hsbc', advisors: null }
]

You could take a multilevel grouping with objects for every level and the data, here with a key _, which not collide with possible keys of grouping.
const
data = [{ name: "john", savings: 900, firm: "chase", advisor: "holly" }, { name: "carol", savings: 500, checking: 600, firm: "chase", advisor: "mark" }, { name: "sarah", savings: 500, checking: 300, firm: "chase", advisor: "holly" }, { name: "toby", savings: 500, checking: 300, firm: "chase", advisor: "mark" }, { name: "casey", savings: 500, checking: 200, firm: "citiBank", advisor: "cindy" }, { name: "bruce", checking: 200, firm: "chase", advisor: "holly" }, { name: "jim", checking: 200, firm: "chase", advisor: "holly" }, { name: "nich", firm: "chase", advisor: "mark" }],
keys = [['firm', 'advisors'], ['advisor', 'clients']],
result = data.reduce((r, o) => {
keys
.reduce((q, [key, children]) => {
({ [key]: name, ...o } = o);
if (!q[name]) {
q[name] = { _: [] };
q._.push({ name, [children]: q[name]._ });
}
return q[name];
}, r)
._
.push(o);
return r;
}, { _: [] })._;
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

You just have to go through the items, grouping them by bank and advisor. If you sort it first, you can keep a current bank and advisor and add to them until you get to the next.
Here is an example:
const data = [ { "name": "john", "savings": 900, "firm": "chase", "advisor": "holly" }, { "name": "carol", "savings": 500, "checking": 600, "firm": "chase", "advisor": "mark" }, { "name": "sarah", "savings": 500, "checking": 300, "firm": "chase", "advisor": "holly" }, { "name": "toby", "savings": 500, "checking": 300, "firm": "chase", "advisor": "mark" }, { "name": "casey", "savings": 500, "checking": 200, "firm": "citiBank", "advisor": "cindy" }, { "name": "bruce", "checking": 200, "firm": "chase", "advisor": "holly" }, { "name": "jim", "checking": 200, "firm": "chase", "advisor": "holly" }, { "name": "nich", "firm": "chase", "advisor": "mark" } ]
const bankData = data
.sort( (e1, e2) => e1.firm.localeCompare(e2.firm) || e1.advisor.localeCompare(e2.advisor) )
.reduce( ([c,a,b], e) => (
c?.name !== e.firm && (b = [...b, (c = {name: e.firm, advisors: []} ) ]),
a?.name !== e.advisor && (c.advisors = [...c.advisors, (a = {name: e.advisor, clients: []})]),
e = Object.fromEntries(Object.entries(e).filter( ([k,v]) => ['name', 'checking'].includes(k))),
a.clients.push(e),
[c,a,b]
), [null, null, []])
.pop()
console.log(bankData)
.as-console-wrapper {max-height: 100% !important;}

This is very much a duplicate as flagged, but since it involves an extra layer of nesting and some minor refactoring of the objects it seems unlikely to be closed. That being said, it can be solved using the duplicate's approach by simply iterating over the array twice.
const data = [{ name: 'john', savings: 900, firm: 'chase', advisor: 'holly', }, { name: 'carol', savings: 500, checking: 600, firm: 'chase', advisor: 'mark', }, { name: 'sarah', savings: 500, checking: 300, firm: 'chase', advisor: 'holly', }, { name: 'toby', savings: 500, checking: 300, firm: 'chase', advisor: 'mark', }, { name: 'casey', savings: 500, checking: 200, firm: 'citiBank', advisor: 'cindy', }, { name: 'bruce', checking: 200, firm: 'chase', advisor: 'holly', }, { name: 'jim', checking: 200, firm: 'chase', advisor: 'holly', }, { name: 'nich', firm: 'chase', advisor: 'mark', },];
const result = Object.values(
data.reduce(
(a, { firm: name, ...obj }) => (
(a[name] ??= { name, advisors: [] }).advisors.push(obj), a
),
{}
)
).map(({ advisors, ...firm }) => ({
...firm,
advisors: Object.values(
advisors.reduce(
(a, { advisor: name, ...obj }) => (
(a[name] ??= { name, clients: [] }).clients.push(obj), a
),
{}
)
),
}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
The above exhibits a great deal of repeated code, but is overall quite readable. We can improve both, readability and repetiton, by abstracting the grouping/refactoring logic into a helper function resulting in the 'group by' logic from the duplicate being clearly visible in the helper, and the use of it in successive loops apparent in the calls assigned to the result.
const data = [{ name: 'john', savings: 900, firm: 'chase', advisor: 'holly', }, { name: 'carol', savings: 500, checking: 600, firm: 'chase', advisor: 'mark', }, { name: 'sarah', savings: 500, checking: 300, firm: 'chase', advisor: 'holly', }, { name: 'toby', savings: 500, checking: 300, firm: 'chase', advisor: 'mark', }, { name: 'casey', savings: 500, checking: 200, firm: 'citiBank', advisor: 'cindy', }, { name: 'bruce', checking: 200, firm: 'chase', advisor: 'holly', }, { name: 'jim', checking: 200, firm: 'chase', advisor: 'holly', }, { name: 'nich', firm: 'chase', advisor: 'mark', },];
const groupBy = (arr, key, accumulator) => {
const grouped = {};
for (const { [key]: name, ...obj } of arr) {
(grouped[name] ??= { name, [accumulator]: [] })[accumulator].push(obj);
}
return Object.values(grouped);
};
const result = groupBy(data, 'firm', 'advisors').map(
({ advisors, ...firm }) => ({
...firm,
advisors: groupBy(advisors, 'advisor', 'clients'),
})
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Or abstract even further to make a completely generic group() function which accepts a callback that that will be passed the accumulator and each iterated object and is responsible for all refactoring. Here using a little currying to share logic between the 'group by firm' and 'group by advisor' callbacks.
const data = [{ name: 'john', savings: 900, firm: 'chase', advisor: 'holly', }, { name: 'carol', savings: 500, checking: 600, firm: 'chase', advisor: 'mark', }, { name: 'sarah', savings: 500, checking: 300, firm: 'chase', advisor: 'holly', }, { name: 'toby', savings: 500, checking: 300, firm: 'chase', advisor: 'mark', }, { name: 'casey', savings: 500, checking: 200, firm: 'citiBank', advisor: 'cindy', }, { name: 'bruce', checking: 200, firm: 'chase', advisor: 'holly', }, { name: 'jim', checking: 200, firm: 'chase', advisor: 'holly', }, { name: 'nich', firm: 'chase', advisor: 'mark', },];
const group = (arr, accumulate) => {
let accumulator = {};
for (const obj of arr) {
accumulator = accumulate(accumulator, obj);
}
return Object.values(accumulator);
};
const by = (parentProp, childProp) => (acc, obj) => {
const { [parentProp]: name, ...child } = obj;
(acc[name] ??= { name, [childProp]: [] })[childProp].push(child);
return acc;
};
const result = group(data, by('firm', 'advisors')).map(
({ advisors, ...firm }) => ({
...firm,
advisors: group(advisors, by('advisor', 'clients')),
})
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Related

How can I turn all the objects founded in Arr.find into a big Array?

I have this function: printRecords which receives an Array of IDs:numbers, and I have to find() and print (before sorting and doing other stuff) the user's object that matches the IDs given as arguments.
So I did the following:
function printRecords(recordIds) {
for (const currId of recordIds) {
const person = studentRecords.find((student) => student.id == currId)
const personArr = Array.of(person)
console.log([...personArr])
}
}
const currentEnrollment = [ 410, 105, 664, 375 ];
var studentRecords = [
{ id: 313, name: "Frank", paid: true, },
{ id: 410, name: "Suzy", paid: true, },
{ id: 709, name: "Brian", paid: false, },
{ id: 105, name: "Henry", paid: false, },
{ id: 502, name: "Mary", paid: true, },
{ id: 664, name: "Bob", paid: false, },
{ id: 250, name: "Peter", paid: true, },
{ id: 375, name: "Sarah", paid: true, },
{ id: 867, name: "Greg", paid: false, },
];
printRecords(currentEnrollment)
I already iterate the argument and found the users object that match ID but now the question is… How I turn it back into an object's array. I thought that Array.of()/ spread would have done it, but instead of taking the objects as a whole it works individually on every one.
the log is:
[ { id: 410, name: 'Suzy', paid: true } ]
[ { id: 105, name: 'Henry', paid: false } ]
[ { id: 664, name: 'Bob', paid: false } ]
[ { id: 375, name: 'Sarah', paid: true } ]
and I need:
[{ id: 410, name: 'Suzy', paid: true },
{ id: 105, name: 'Henry', paid: false },
{ id: 664, name: 'Bob', paid: false },
{ id: 375, name: 'Sarah', paid: true } ]
Thanks in advance.
You can simplify the logic by using filter() and includes() to find the matches. This will already return the array you need without any further amendments:
function printRecords(recordIds) {
let personArr = studentRecords.filter(record => recordIds.includes(record.id));
console.log(personArr)
}
const currentEnrollment = [410, 105, 664, 375];
var studentRecords = [
{ id: 313, name: "Frank", paid: true, },
{ id: 410, name: "Suzy", paid: true, },
{ id: 709, name: "Brian", paid: false, },
{ id: 105, name: "Henry", paid: false, },
{ id: 502, name: "Mary", paid: true, },
{ id: 664, name: "Bob", paid: false, },
{ id: 250, name: "Peter", paid: true, },
{ id: 375, name: "Sarah", paid: true, },
{ id: 867, name: "Greg", paid: false, },
];
printRecords(currentEnrollment)

Using reduce to get sum of an object

I want to have a sum of all the particulars which are in selectedIds array.
return [
{
id: 1244,
name: "Installment 1",
amount: 10000,
due_date: new Date(),
particulars: [
{
id: 2415123,
name: "Development Fee",
amount: 5000,
},
{
id: 14123,
name: "Library Fee",
amount: 3000,
},
{
id: 5123151,
name: "Sports Fee",
amount: 2000,
},
]
},
{
id: 1412,
name: "Installment 2",
amount: 6000,
due_date: new Date(),
particulars: [
{
id: 414,
name: "Development Fee",
amount: 5000,
},
{
id: 5123,
name: "Library Fee",
amount: 3000,
},
{
id: 515151,
name: "Sports Fee",
amount: 2000,
},
]
const selectedIds = [14123, 414];
In the object, I want to have a sum of all the particulars which are in selectedIds array.
I was trying to use array function to get the result. This is what I could come up with.
const selectedInstallments = this.studentInstallments
.filter((installment) =>
installment.particulars.some((particular) =>
this.selectedParticulars.includes(particular.id)
)
)
.map((installment) => installment.particulars);
console.log(selectedInstallments);
const sumParticularReducer = (acc, current) => {
return acc;
};
I couldn't figure out how to use reduce to get the result.
Please try this code.
const selectedIds = [14123, 414];
const sum = arr.reduce((prev, cur) => {
return prev + cur.particulars.reduce((old, item) => (
selectedIds.indexOf(item.id) >= 0 ? old + item.amount : old
), 0);
}, 0);
console.log(sum);
Something like:
const selectedIds = [14123, 414];
const idsArray = [{
id: 1244,
name: "Installment 1",
amount: 10000,
due_date: new Date(),
particulars: [{
id: 2415123,
name: "Development Fee",
amount: 5000,
},
{
id: 14123,
name: "Library Fee",
amount: 3000,
},
{
id: 5123151,
name: "Sports Fee",
amount: 2000,
},
]
},
{
id: 1412,
name: "Installment 2",
amount: 6000,
due_date: new Date(),
particulars: [{
id: 414,
name: "Development Fee",
amount: 5000,
},
{
id: 5123,
name: "Library Fee",
amount: 3000,
},
{
id: 515151,
name: "Sports Fee",
amount: 2000,
},
]
}
]
const sum = idsArray.reduce((sum, value) => sum + value.particulars.reduce(
(partSum, partValue) => selectedIds.includes(partValue.id) ? (partSum + partValue.amount) : partSum, 0),
0
);
console.log(sum);
const data = [{
id: 1244,
name: "Installment 1",
amount: 10000,
due_date: new Date(),
particulars: [{
id: 2415123,
name: "Development Fee",
amount: 5000,
},
{
id: 14123,
name: "Library Fee",
amount: 3000,
},
{
id: 5123151,
name: "Sports Fee",
amount: 2000,
},
]
},
{
id: 1412,
name: "Installment 2",
amount: 6000,
due_date: new Date(),
particulars: [{
id: 414,
name: "Development Fee",
amount: 5000,
},
{
id: 5123,
name: "Library Fee",
amount: 3000,
},
{
id: 515151,
name: "Sports Fee",
amount: 2000,
},
]
}
]
const selectedIds = [14123, 414];
const result = selectedIds.reduce(
(acc, id) => acc + data.reduce(
(acc, { particulars }) =>
acc + (particulars.find(p => p.id === id)?.amount || 0)
, 0)
, 0)
console.log(result)

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

JavaScript ES6 better way to transform complex object

I am trying to transform complex JavaScript object. Below is my code. As you can see, it's a lot of code. I am looking for a better/common way to achieve the same result. Maybe ES6 map/Reduce? (I am not allow to do import/require)
function test() {
var input = {
number: 555,
obj1: {
fld1: "11",
persons: [
{
name: "smith",
phone: "222-222-2222"
}
],
},
obj2: {
obj3: {
day: "2019-02-04"
}
},
myArr: [
{
number: 444,
qty: 20,
unit: "ton",
item: {
item_id: 1,
description: "item 1"
}
},
{
number: 111,
qty: 15,
unit: "pieces",
item: {
item_id: 2,
description: "item 2"
}
}
]
}
var result = {
id: input.number,
object1: {
id: input.obj1.number,
contacts: getArr2(input)
},
object2: {
date: input.obj2.obj3.day,
},
list: getArr1(input),
}
return result; // echo back the input received
}
console.log(JSON.stringify(test()));
function getArr1(input) {
var arr = [];
input.myArr.forEach(function (prod) {
let p = {
id: prod.number,
itemId: prod.item.item_id,
description: prod.item.description,
quantity: {
value: prod.qty,
uom: prod.unit
}
}
arr.push(p);
});
return arr;
}
function getArr2(input) {
var arr = [];
input.obj1.persons.forEach(function (person) {
let p = {
name: person.name,
cell: person.phone
}
arr.push(p);
});
return arr;
}
And the result is
{
"id": 555,
"object1": {
"contacts": [{
"name": "smith",
"cell": "222-222-2222"
}]
},
"object2": {
"date": "2019-02-04"
},
"list": [{
"id": 444,
"itemId": 1,
"description": "item 1",
"quantity": {
"value": 20,
"uom": "ton"
}
}, {
"id": 111,
"itemId": 2,
"description": "item 2",
"quantity": {
"value": 15,
"uom": "pieces"
}
}]
}
You could use the power of destructuring and renaming.
function getProds(products) {
return products.map(({ number: id, qty: value, unit: uom, item: { item_id: itemId, description } }) =>
({ id, itemId, description, quantity: { value, uom } }));
}
function getPersons(persons) {
return persons.map(({ name, phone: cell }) => ({ name, cell }));
}
function convert({ number: id, obj1, obj2: { obj3: { day: date } }, myArr }) {
return {
id,
object1: {
id: obj1.number,
contacts: getPersons(obj1.persons)
},
object2: { date },
list: getProds(myArr)
};
}
var data = { number: 555, obj1: { fld1: "11", persons: [{ name: "smith", phone: "222-222-2222" }], }, obj2: { obj3: { day: "2019-02-04" } }, myArr: [{ number: 444, qty: 20, unit: "ton", item: { item_id: 1, description: "item 1" } }, { number: 111, qty: 15, unit: "pieces", item: { item_id: 2, description: "item 2" } }] };
console.log(convert(data));
.as-console-wrapper { max-height: 100% !important; top: 0; }
You're on the right track with map/reduce.
Here's an example (getArr1 would be similar):
function getArr2(input) {
// Don't need map if new object is identical
// Could also do the mapping within the reduce callback
return input.obj1.persons
.map(person => ({ name: person.name, cell: person.phone }))
.reduce((accumulator, currentValue) => {
accumulator.push(currentValue);
return accumulator;
}, []);
}
There's another example in the documentation at: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce#Remove_duplicate_items_in_array

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

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

Categories