Merge & get then push to one array - javascript

I have data like this:
let data = []
let weeks = [
{
"week": 1,
"crop": {
"aop": 1,
"actual": 2,
"kbm": 3
},
"hk": {
"aop": 4,
"actual": 5,
"kbm": 6
},
"outputHkAct": 7
},
{
"week": 2,
"crop": {
"aop": 11,
"actual": 12,
"kbm": 13
},
"hk": {
"aop": 14,
"actual": 15,
"kbm": 16
},
"outputHkAct": 17
},
]
i wanth to merge & get the value every week in crop(aop, actual, kbm), outputHkAct , hk(aop, actual, kbm), outputHkAct.
the output should be :
data = [1, 2, 3, 4, 5, 6, 7, 11, 12, 13, 14, 15, 16, 17]
anyone can help? thanks guys.

It can be solved by using forEach:
let data = []
let weeks = [
{
"week": 1,
"crop": {
"aop": 1,
"actual": 2,
"kbm": 3
},
"hk": {
"aop": 4,
"actual": 5,
"kbm": 6
},
"outputHkAct": 7
},
{
"week": 2,
"crop": {
"aop": 11,
"actual": 12,
"kbm": 13
},
"hk": {
"aop": 14,
"actual": 15,
"kbm": 16
},
"outputHkAct": 17
},
]
weeks.forEach(({crop,hk,outputHkAct})=>{
data.push(crop.aop);
data.push(crop.actual);
data.push(crop.kbm);
data.push(hk.aop);
data.push(hk.actual);
data.push(hk.kbm);
data.push(outputHkAct)
})
console.log(data)

You can suer for in loop which helps you to loop through an object
let weeks = [
{
"week": 1,
"crop": {
"aop": 1,
"actual": 2,
"kbm": 3
},
"hk": {
"aop": 4,
"actual": 5,
"kbm": 6
},
"outputHkAct": 7
},
{
"week": 2,
"crop": {
"aop": 11,
"actual": 12,
"kbm": 13
},
"hk": {
"aop": 14,
"actual": 15,
"kbm": 16
},
"outputHkAct": 17
},
]
let allValues = [];
weeks.map(obj=>{
for(let key in obj){
if(key === 'crop' || key === 'hk'){
for(let k in obj[key]){
allValues.push(obj[key][k])
}
}else if(key === 'outputHkAct'){
allValues.push(obj[key])
}
}
})
console.log(allValues)

weeks is an array of object.
So you have to iterate through weeks array (by using for-of, for-in, while, map, reduce, etc.) to get the object and now you can access the value of the object by using a key which you already know (crop(aop, actual, kbm), outputHkAct , hk(aop, actual, kbm), outputHkAct).
Here is the example by using reduce.
let weeks = [
{
"week": 1,
"crop": {
"aop": 1,
"actual": 2,
"kbm": 3
},
"hk": {
"aop": 4,
"actual": 5,
"kbm": 6
},
"outputHkAct": 7
},
{
"week": 2,
"crop": {
"aop": 11,
"actual": 12,
"kbm": 13
},
"hk": {
"aop": 14,
"actual": 15,
"kbm": 16
},
"outputHkAct": 17
},
];
let data = [...weeks.reduce((v, { crop, hk, outputHkAct }) => [...v, ...Object.values(crop), ...Object.values(hk), outputHkAct], [])];
console.log(data);

Related

Filtering array objects with nested properties from another array objects properties in Javascript [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed last year.
Improve this question
I have 2 arrays structured like this :
const products = [
{
id: 1,
name: 'Table',
attributes: [
{ id: 13, prodId: 1, attribute_id: 1, attribute_value_id: 8 },
{ id: 14, prodId: 1, attribute_id: 2, attribute_value_id: 19 },
{ id: 15, prodId: 1, attribute_id: 3, attribute_value_id: 88 },
{ id: 16, prodId: 1, attribute_id: 4, attribute_value_id: 237 },
],
},
{
id: 2,
name: 'Chair',
attributes: [
{ id: 25, prodId: 2, attribute_id: 1, attribute_value_id: 2 },
{ id: 26, prodId: 2, attribute_id: 2, attribute_value_id: 21 },
{ id: 27, prodId: 2, attribute_id: 3, attribute_value_id: 127 },
{ id: 28, prodId: 2, attribute_id: 4, attribute_value_id: 240 },
],
},
{
id: 3,
name: 'Couch',
attributes: [
{ id: 41, prodId: 3, attribute_id: 1, attribute_value_id: 8 },
{ id: 42, prodId: 3, attribute_id: 2, attribute_value_id: 18 },
{ id: 43, prodId: 3, attribute_id: 3, attribute_value_id: 88 },
{ id: 44, prodId: 3, attribute_id: 5, attribute_value_id: 271 },
],
},
{
id: 4,
name: 'Rug',
attributes: [
{ id: 75, prodId: 4, attribute_id: 1, attribute_value_id: 2 },
{ id: 76, prodId: 4, attribute_id: 2, attribute_value_id: 19 },
{ id: 77, prodId: 4, attribute_id: 3, attribute_value_id: 89 },
{ id: 78, prodId: 4, attribute_id: 4, attribute_value_id: 256 },
],
},
]
const filters = [
{ attribute_id: 1, attribute_value_id: '8' },
{ attribute_id: 3, attribute_value_id: '88' },
]
How can I filter objects from the "products" array that matches at least all criteria from the "filters" array, no matter how many products are there, nor how many attributes each product has ?
In the above case, I would like to get the result :
[{
id: 1,
name: 'Table',
attributes: [
{ id: 13, prodId: 1, attribute_id: 1, attribute_value_id: 8 },
{ id: 14, prodId: 1, attribute_id: 2, attribute_value_id: 19 },
{ id: 15, prodId: 1, attribute_id: 3, attribute_value_id: 88 },
{ id: 16, prodId: 1, attribute_id: 4, attribute_value_id: 237 },
],
},
{
id: 3,
name: 'Couch',
attributes: [
{ id: 41, prodId: 3, attribute_id: 1, attribute_value_id: 8 },
{ id: 42, prodId: 3, attribute_id: 2, attribute_value_id: 18 },
{ id: 43, prodId: 3, attribute_id: 3, attribute_value_id: 88 },
{ id: 44, prodId: 3, attribute_id: 5, attribute_value_id: 271 },
],
}]
Edit : I've tried to start from something like this :
const filteredProducts = products.filter((p)=>{
return filters.some((f)=>{
// another loop ?
});
});
console.log(filteredProducts);
but couldn't manage to loop through each product's nested attributes and through filters when there's many of them
NB : product "couch" having an attribute with "attribute_id" of 5 instead of 4 is not a typo
Hoping I'm clear enough, thanks in advance !
Yes, you need another loop.
From what you've said ... at least all criteria from the "filters", you'd have to use filters.every and not filters.some. And then for each you'll have to iterate over the key value pairs (Object.entries) and see if any of the objects in the attributes array matches (use some).
So use combinations of every and some`, like so:
function filterByAttributes(products, filters) {
return products.filter(({attributes}) =>
filters.every(filter =>
Object.entries(filter).every(([key, value]) =>
attributes.some(obj => obj[key] == value)
)
)
);
}
const products = [{id: 1,name: 'Table',attributes: [{ id: 13, prodId: 1, attribute_id: 1, attribute_value_id: 8 },{ id: 14, prodId: 1, attribute_id: 2, attribute_value_id: 19 },{ id: 15, prodId: 1, attribute_id: 3, attribute_value_id: 88 },{ id: 16, prodId: 1, attribute_id: 4, attribute_value_id: 237 },],},{id: 2,name: 'Chair',attributes: [{ id: 25, prodId: 2, attribute_id: 1, attribute_value_id: 2 },{ id: 26, prodId: 2, attribute_id: 2, attribute_value_id: 21 },{ id: 27, prodId: 2, attribute_id: 3, attribute_value_id: 127 },{ id: 28, prodId: 2, attribute_id: 4, attribute_value_id: 240 },],},{id: 3,name: 'Couch',attributes: [{ id: 41, prodId: 3, attribute_id: 1, attribute_value_id: 8 },{ id: 42, prodId: 3, attribute_id: 2, attribute_value_id: 18 },{ id: 43, prodId: 3, attribute_id: 3, attribute_value_id: 88 },{ id: 44, prodId: 3, attribute_id: 5, attribute_value_id: 271 },],},{id: 4,name: 'Rug',attributes: [{ id: 75, prodId: 4, attribute_id: 1, attribute_value_id: 2 },{ id: 76, prodId: 4, attribute_id: 2, attribute_value_id: 19 },{ id: 77, prodId: 4, attribute_id: 3, attribute_value_id: 89 },{ id: 78, prodId: 4, attribute_id: 4, attribute_value_id: 256 },],},]
const filters = [{ attribute_id: 1, attribute_value_id: '8' },{ attribute_id: 3, attribute_value_id: '88' },];
console.log(filterByAttributes(products, filters));

Reduce array of objects by user_id and sum certain values

I have an array of objects that looks like this:
"data": [
{ "workout_id": 1, "user_id": 1, "shotLocation": 27, "shotAttempts": 20,"shotsMade": 19, "id": 1 },
{ "workout_id": 2, "user_id": 1, "shotLocation": 1, "shotAttempts": 10, "shotsMade": 9, "id": 2 },
{ "workout_id": 2, "user_id": 1, "shotLocation": 10, "shotAttempts": 10, "shotsMade": 7, "id": 3 },
{ "workout_id": 2, "user_id": 1, "shotLocation": 1, "shotAttempts": 30, "shotsMade": 29, "id": 4 },
{ "workout_id": 3, "user_id": 5, "shotLocation": 1, "shotAttempts": 10, "shotsMade": 9, "id": 5 },
{ "workout_id": 4, "user_id": 6, "shotLocation": 1, "shotAttempts": 30, "shotsMade": 15, "id": 6 },
{ "workout_id": 4, "user_id": 6, "shotLocation": 2, "shotAttempts": 20, "shotsMade": 14, "id": 7 }
]
I would like to create a new array of objects where I
reduce the user_ids to each unique user
then calculate the total shotAttempts and shotsMade for each user
like this:
"dataTotals" : [
{"id": 1, "user_id": 1, "shotAttempts": 90, "shotsMade": 64}
{"id": 2, "user_id": 5, "shotAttempts": 10, "shotsMade": 9}
{"id": 3, "user_id": 6, "shotAttempts": 50, "shotsMade": 29}
I plan on iterating over this new array of objects with a .map function to populate a leaderboard as more users record their data.
I've tried several different ways to achieve this based on what I've read about the .map and .reduce methods, as well as searching here and found something that's close, but it returns an object as indicated below.
like this:
// create new object to store results in
let newObj = {};
// loop through user objects
this.state.shotlogs.forEach(function(shotlog){
// check if user_id has already been added to newObj
if(!newObj[shotlog.user_id]){
// If it is the first time seeing this user_id
// we need to add shots attempted and shots made to prevent errors
newObj[shotlog.user_id] = {};
newObj[shotlog.user_id]['user_id'] = shotlog.user_id;
newObj[shotlog.user_id]['shotAttempts'] = 0;
newObj[shotlog.user_id]['shotsMade'] = 0;
}
// add shots attempted and made to newObj for this user
newObj[shotlog.user_id]['shotAttempts'] += shotlog.shotAttempts
newObj[shotlog.user_id]['shotsMade'] += shotlog.shotsMade
})
but this returns an object that looks like this and not an array of objects like above:
{
1: {user_id: 1, shotAttempts: 70, shotsMade: 64}
5: {user_id: 5, shotAttempts: 10, shotsMade: 9}
6: {user_id: 6, shotAttempts: 50, shotsMade: 29}
}
Any help for this new coder is greatly appreciated!!
const data = [
{ workout_id: 1, user_id: 1, shotLocation: 27, shotAttempts: 20, shotsMade: 19, id: 1 },
{ workout_id: 2, user_id: 1, shotLocation: 1, shotAttempts: 10, shotsMade: 9, id: 2 },
{ workout_id: 2, user_id: 1, shotLocation: 10, shotAttempts: 10, shotsMade: 7, id: 3 },
{ workout_id: 2, user_id: 1, shotLocation: 1, shotAttempts: 30, shotsMade: 29, id: 4 },
{ workout_id: 3, user_id: 5, shotLocation: 1, shotAttempts: 10, shotsMade: 9, id: 5 },
{ workout_id: 4, user_id: 6, shotLocation: 1, shotAttempts: 30, shotsMade: 15, id: 6 },
{ workout_id: 4, user_id: 6, shotLocation: 2, shotAttempts: 20, shotsMade: 14, id: 7 }
];
const shooters = data.reduce(
(results, current) => ({
...results,
[current.user_id]: {
user_id: current.user_id,
shotAttempts: current.shotAttempts + (results[current.user_id] ? results[current.user_id].shotAttempts : 0),
shotsMade: current.shotsMade + (results[current.user_id] ? results[current.user_id].shotsMade : 0)
}
}),
{}
);
console.log(shooters);
You can use Array.reduce, Object.values with ES6 destructuring and solve this in a concise manner:
const data = [{ "workout_id": 1, "user_id": 1, "shotLocation": 27, "shotAttempts": 20, "shotsMade": 19, "id": 1 }, { "workout_id": 2, "user_id": 1, "shotLocation": 1, "shotAttempts": 10, "shotsMade": 9, "id": 2 }, { "workout_id": 2, "user_id": 1, "shotLocation": 10, "shotAttempts": 10, "shotsMade": 7, "id": 3 }, { "workout_id": 2, "user_id": 1, "shotLocation": 1, "shotAttempts": 30, "shotsMade": 29, "id": 4 }, { "workout_id": 3, "user_id": 5, "shotLocation": 1, "shotAttempts": 10, "shotsMade": 9, "id": 5 }, { "workout_id": 4, "user_id": 6, "shotLocation": 1, "shotAttempts": 30, "shotsMade": 15, "id": 6 }, { "workout_id": 4, "user_id": 6, "shotLocation": 2, "shotAttempts": 20, "shotsMade": 14, "id": 7 } ]
const result = data.reduce((r,{workout_id, user_id, shotAttempts, shotsMade}) => {
r[user_id] = r[user_id] || {id: workout_id, user_id, shotAttempts: 0, shotsMade: 0}
r[user_id].shotAttempts += shotAttempts
r[user_id].shotsMade += shotsMade
return r
}, {})
console.log(Object.values(result))
You can use Array.prototype.reduce()
Code:
const data = [{ "workout_id": 1, "user_id": 1, "shotLocation": 27, "shotAttempts": 20,"shotsMade": 19, "id": 1 },{ "workout_id": 2, "user_id": 1, "shotLocation": 1, "shotAttempts": 10, "shotsMade": 9, "id": 2 },{ "workout_id": 2, "user_id": 1, "shotLocation": 10, "shotAttempts": 10, "shotsMade": 7, "id": 3 },{ "workout_id": 2, "user_id": 1, "shotLocation": 1, "shotAttempts": 30, "shotsMade": 29, "id": 4 },{ "workout_id": 3, "user_id": 5, "shotLocation": 1, "shotAttempts": 10, "shotsMade": 9, "id": 5 },{ "workout_id": 4, "user_id": 6, "shotLocation": 1, "shotAttempts": 30, "shotsMade": 15, "id": 6 },{ "workout_id": 4, "user_id": 6, "shotLocation": 2, "shotAttempts": 20, "shotsMade": 14, "id": 7 }];
const dataTotals = Object.values(data.reduce((a, c) => {
if (!a[c.user_id]) {
a[c.user_id] = {
id: c.workout_id,
user_id: c.user_id,
shotAttempts: c.shotAttempts,
shotsMade: c.shotsMade
};
} else {
a[c.user_id].shotAttempts += c.shotAttempts;
a[c.user_id].shotsMade += c.shotsMade;
}
return a;
}, {}));
console.log(dataTotals);

return Object.keys in a map got undefined

What's wrong with my loop below? I want to calculate the total_count and return [total, total] after some manipulation within a map, but I got undefined.
my raw data
const raw = [{
"device_info": {
"name": "cam1",
},
"age_range": {
"0-10": {
"age_range": "0-10",
"total_count": 15,
"male_count": 6,
"female_count": 9
},
"11-20": {
"age_range": "11-20",
"total_count": 11,
"male_count": 7,
"female_count": 4
},
"21-30": {
"age_range": "21-30",
"total_count": 922,
"male_count": 452,
"female_count": 470
}
}
}, {
"device_info": {
"name": "cam2",
},
"age_range": {
"0-10": {
"age_range": "0-10",
"total_count": 1,
"male_count": 1,
"female_count": 0
},
"11-20": {
"age_range": "11-20",
"total_count": 2,
"male_count": 0,
"female_count": 2
},
"21-30": {
"age_range": "21-30",
"total_count": 90,
"male_count": 58,
"female_count": 32
}
}
}]
Loop
const x = raw.map(obj => {
return Object.keys(obj).forEach(key => {
let total = 0
if (key === 'age_range') {
total = Object.keys(obj.age_range).reduce((acum, innerKey) => {
return acum + obj.age_range[innerKey].total_count
}, 0)
console.log(total)
}
});
})
console.log('x', x)
https://jsfiddle.net/19m3f7fs/1
Array#forEach doesn't return anything, use Array#map and Object.values instead:
const x = raw.map(obj => {
return Object.values(obj.age_range).reduce((acc, item) => acc + item.total_count, 0)
})
Working example:
const raw = [{
"device_info": {
"name": "cam1",
},
"age_range": {
"0-10": {
"age_range": "0-10",
"total_count": 15,
"male_count": 6,
"female_count": 9
},
"11-20": {
"age_range": "11-20",
"total_count": 11,
"male_count": 7,
"female_count": 4
},
"21-30": {
"age_range": "21-30",
"total_count": 922,
"male_count": 452,
"female_count": 470
}
}
}, {
"device_info": {
"name": "cam2",
},
"age_range": {
"0-10": {
"age_range": "0-10",
"total_count": 1,
"male_count": 1,
"female_count": 0
},
"11-20": {
"age_range": "11-20",
"total_count": 2,
"male_count": 0,
"female_count": 2
},
"21-30": {
"age_range": "21-30",
"total_count": 90,
"male_count": 58,
"female_count": 32
}
}
}]
const x = raw.map(obj => Object.values(obj.age_range).reduce((acc, item) => acc + item.total_count, 0))
console.log(x)
Your problem is, that the raw.map returns whatever comes from Object.key(obj).forEach(...)
But for each is just an "iterator" function. It actually doesnt return anything.
See: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach
Change like this .define the total in first map varible and remove the return from forEach.ForEach not returning anything .And add the return satement only inside the first map.
const raw = [{
"device_info": {
"name": "cam1",
},
"age_range": {
"0-10": {
"age_range": "0-10",
"total_count": 15,
"male_count": 6,
"female_count": 9
},
"11-20": {
"age_range": "11-20",
"total_count": 11,
"male_count": 7,
"female_count": 4
},
"21-30": {
"age_range": "21-30",
"total_count": 922,
"male_count": 452,
"female_count": 470
}
}
}, {
"device_info": {
"name": "cam2",
},
"age_range": {
"0-10": {
"age_range": "0-10",
"total_count": 1,
"male_count": 1,
"female_count": 0
},
"11-20": {
"age_range": "11-20",
"total_count": 2,
"male_count": 0,
"female_count": 2
},
"21-30": {
"age_range": "21-30",
"total_count": 90,
"male_count": 58,
"female_count": 32
}
}
}]
const x = raw.map(obj => {
let total = 0
Object.keys(obj).forEach(key => {
if (key === 'age_range') {
total = Object.keys(obj.age_range).reduce((acum, innerKey) => {
return acum + obj.age_range[innerKey].total_count
}, 0)
}
});
return total
})
console.log('x', x)

Add values to an object from another array of objects

So i have this scope with a predefined equipment:
$scope.equipment = [
{slot: 7, colspan: 2, rowspan: 1},
{slot: 0, colspan: 2, rowspan: 2},
{slot: 10, colspan: 2, rowspan: 1},
{slot: 8, colspan: 1, rowspan: 1},
{slot: 9, colspan: 1, rowspan: 1},
{slot: 6, colspan: 2, rowspan: 1},
{slot: 17, colspan: 1, rowspan: 1},
{slot: 18, colspan: 1, rowspan: 1},
{slot: 1, colspan: 2, rowspan: 4},
{slot: 19, colspan: 2, rowspan: 1},
{slot: 4, colspan: 2, rowspan: 4},
{slot: 5, colspan: 2, rowspan: 4},
{slot: 14, colspan: 1, rowspan: 1},
{slot: 15, colspan: 1, rowspan: 1},
{slot: 2, colspan: 2, rowspan: 2},
{slot: 16, colspan: 1, rowspan: 1},
{slot: 15, colspan: 1, rowspan: 1},
{slot: 3, colspan: 2, rowspan: 2}
];
As you can see, each slot has its own colspan and rowspan.
Than i have the equipment items array of objects:
$scope.equipmentItems = [
{
"id": 282,
"upgrade": 15,
"bind": 1,
"slot": 0,
"name": "Archridium Headpiece (BL)"
},
{
"id": 147,
"upgrade": 15,
"bind": 1,
"slot": 1,
"name": "Archridium Suit (BL)"
},
{
"id": 192,
"upgrade": 15,
"bind": 1,
"slot": 2,
"name": "Archridium Hands (BL)"
},
{
"id": 237,
"upgrade": 15,
"bind": 1,
"slot": 3,
"name": "Archridium Shoes (BL)"
},
{
"id": 3706,
"upgrade": 0,
"bind": 0,
"slot": 4
},
{
"id": 3707,
"upgrade": 0,
"bind": 0,
"slot": 5
},
{
"id": 3622,
"upgrade": 0,
"bind": 0,
"slot": 6
},
{
"id": 408,
"upgrade": 0,
"bind": 0,
"slot": 7,
"name": "Amulet Of Pain +7",
"description": "Protect you from enemy's attacks and to give more chance to do Critical Attacks. "
},
{
"id": 3194,
"upgrade": 0,
"bind": 0,
"slot": 8,
"name": "Ring of Luck +3",
"description": "Increases your Critical Hit Rate."
},
{
"id": 3193,
"upgrade": 0,
"bind": 0,
"slot": 9,
"name": "Critical Ring +3",
"description": "Increases your Critical Attack Damage."
},
{
"id": 2371,
"upgrade": 0,
"bind": 1,
"slot": 10,
"name": "Astral Board Card - K Red Crystal Edition",
"description": "A mysterious card that summons Astral Board, one of the valuable Honorable Age's legacies and the essence of Core Technology. - K Red Crystal Edition_$4#(Right click to use) "
},
{
"id": 3607,
"upgrade": 0,
"bind": 0,
"slot": 13
},
{
"id": 3607,
"upgrade": 0,
"bind": 0,
"slot": 14
},
: {
"id": 3604,
"upgrade": 0,
"bind": 0,
"slot": 15
},
{
"id": 3604,
"upgrade": 0,
"bind": 0,
"slot": 16
},
{
"id": 2568,
"upgrade": 0,
"bind": 4,
"slot": 17,
"name": "Leth Tyrant's Ring",
"description": "This ring contains the sealed power of Leth Tyrant, the extraordinary monster created by the Doctor. "
},
{
"id": 3184,
"upgrade": 0,
"bind": 4,
"slot": 18,
"name": "Killian's Ring",
"description": "This generates powerful energy from the combination of Killian's Dark Energy and the grudge of the Black Cat, the Guardian of Hell."
},
"{
"id": 2228,
"upgrade": 0,
"bind": 0,
"slot": 19,
"name": "Belt of Damp +4",
"description": "This belt reduces damage from intensified sword or magic attacks. "
}
];
As you can see each object key is basically the slot id.
Than i use this code
$scope.equipmentItems = _.sortBy($scope.equipmentItems, function(obj) {
return _.indexOf([7, 0, 10, 8, 9, 6, 17, 18, 1, 19, 4, 5, 14, 13, 2, 16, 15, 3], obj.slot);
});
to sort the equipment items keys to my specific order.
Anyway, what i want is the most performant piece of code that can add the values colspan and rowspan from $scope.equipment to $scope.equipmentItems WHERE $scope.equipment slot correspond to $scope.equipmentItems slot.
You can use Array functions. Something like this:
let merged = equipmentItems.map(item=>{
item.anotherKey = equipment.find(it=> it.slot == item.slot);
return item;
});
If you don't like this, or you can't use those methods you can use forEach
equipmentItems.forEach(function(item){
equipment.forEach(function(item_){
if(item.slot == item_.slot){
item.someKey = item_;
}
});
});

Summarize array values, underscore

Got this array:
var arr = [
{
series: [
{
"name": 2014,
"data": [19, 17, 15, 12, 10, 10, 12, 10, 11, 14, 14, 18]
},
{
"name": 2015,
"data": [18, 17, 16, 12, 10, 7, 6, 8, 8, 11, 15, 30]
},
]
},
{
series: [
{
"name": 2014,
"data": [32, 17, 15, 12, 33 10, 33, 10, 11, 14, 14, 18]
},
{
"name": 2015,
"data": [45, 10, 12, 55, 77, 7, 6, 8, 8, 11, 33, 30]
},
]
},
]
I need to create a function that returns a summrized series:
var series = [
{
year: '2014',
data: [51, 34....],
},
{
year: '2015',
data: [63, 27....],
}
]
I could to loops to do this but I guess there is some smart way of doing with underscore? Probably with the reduce function. Any ideas of how to do this?
var arr = [{
"series": [{
"name": 2014,
"data": [19, 17, 15, 12, 10, 10, 12, 10, 11, 14, 14, 18]
}, {
"name": 2015,
"data": [18, 17, 16, 12, 10, 7, 6, 8, 8, 11, 15, 30]
}]
}, {
"series": [{
"name": 2014,
"data": [19, 17, 15, 12, 10, 10, 12, 10, 11, 14, 14, 18]
}, {
"name": 2015,
"data": [18, 17, 16, 12, 10, 7, 6, 8, 8, 11, 15, 30]
}]
}];
_.chain(arr)
.map('series')
.flatten()
.reduce(function(object, value) {
object[value.name] = !object[value.name] ? value.data : _.union(object[value.data], value.data);
return object;
}, {})
.reduce(function(arr, value, key) {
arr.push({
year: key,
data: value
});
return arr;
}, [])
.value();
You could use some iterations and an object as reference to the year for grouping.
var arr = [{ series: [{ "name": 2014, "data": [19, 17, 15, 12, 10, 10, 12, 10, 11, 14, 14, 18] }, { "name": 2015, "data": [18, 17, 16, 12, 10, 7, 6, 8, 8, 11, 15, 30] }] }, { series: [{ "name": 2014, "data": [32, 17, 15, 12, 33, 10, 33, 10, 11, 14, 14, 18] }, { "name": 2015, "data": [45, 10, 12, 55, 77, 7, 6, 8, 8, 11, 33, 30] }] }],
series = [];
arr.forEach(function (a) {
Object.keys(a).forEach(function (k) {
a[k].forEach(function (b) {
if (!this[b.name]) {
this[b.name] = { year: b.name, data: [] };
series.push(this[b.name]);
}
b.data.forEach(function (c, i) {
this[b.name].data[i] = (this[b.name].data[i] || 0) + c;
}, this);
}, this);
}, this);
}, {});
document.write('<pre>' + JSON.stringify(series, 0, 4) + '</pre>');

Categories