问题
I have an array of an object like this
[
{
'a': 10,
elements: [
{
'prop': 'foo',
'val': 10
},
{
'prop': 'bar',
'val': 25
},
{
'prop': 'test',
'val': 51
}
]
},
{
'b': 50,
elements: [
{
'prop': 'foo',
'val': 30
},
{
'prop': 'bar',
'val': 15
},
{
'prop': 'test',
'val': 60
}
]
},
]
What I need is sum the property Val when prop is foo.
So, I have to search through elements and get all objects where prop is foo. With this objects, I should sum the val property.
I tried to use many combinations of _.find, _.pick and so on, but I don't get the right result. Can someone help me?
回答1:
Here's a solution that flattens the elements and then filters the result to get the required elements before summing the val property:
var result = _.chain(data)
.map('elements') // pluck all elements from data
.flatten() // flatten the elements into a single array
.filter({prop: 'foo'}) // exatract elements with a prop of 'foo'
.sumBy('val') // sum all the val properties
.value()
Chaining is a way of applying a sequence of operations to some data before returning a value. The above example uses explicit chaining but could be (maybe should be) written using implicit chaining:
var result = _(data)
.map('elements')
.flatten()
.filter({prop: 'foo'})
.sumBy('val');
回答2:
I've created library that you can use: https://github.com/dominik791/obj-traverse
findAll() method should solve your problem. The first parameter is a root object, not array, so you should create it at first:
var rootObj = {
name: 'rootObject',
elements: [
{
'a': 10,
elements: [ ... ]
},
{
'b': 50,
elements: [ ... ]
}
]
};
Then use findAll() method:
var matchingObjects = findAll( rootObj, 'elements', { 'prop': 'foo' } );
matchingObjects variable stores all objects with prop equal to foo. And at the end calculate your sum:
var sum = 0;
matchingObjects.forEach(function(obj) {
sum += obj.val;
});
回答3:
You can use _.eachDeep method from deepdash:
let sum = 0;
_.eachDeep(obj, (value, key, parent) => {
sum += (key == 'prop' && value == 'foo' && parent.val) || 0;
});
here is an example for your case
回答4:
You can loop through the data and get the sum.Try this:
var arr=[
{
'a': 10,
elements: [
{
'prop': 'foo',
'val': 10
},
{
'prop': 'bar',
'val': 25
},
{
'prop': 'test',
'val': 51
}
]
},
{
'b': 50,
elements: [
{
'prop': 'foo',
'val': 30
},
{
'prop': 'bar',
'val': 15
},
{
'prop': 'test',
'val': 60
}
]
}
];
var sum=0;
for(x in arr){
for(i in arr[x]['elements']){
if(arr[x]['elements'][i]['prop'] == 'foo'){
sum=sum+arr[x]['elements'][i]['val'];
}
}
}
console.log(sum);
USING FILTER:
var arr=[
{
'a': 10,
elements: [
{
'prop': 'foo',
'val': 10
},
{
'prop': 'bar',
'val': 25
},
{
'prop': 'test',
'val': 51
}
]
},
{
'b': 50,
elements: [
{
'prop': 'foo',
'val': 30
},
{
'prop': 'bar',
'val': 15
},
{
'prop': 'test',
'val': 60
}
]
}
];
var sum=0;
arr.filter(function (person) {
person['elements'].filter(function(data){
if (data.prop == "foo"){
sum=sum+data.val;
}
});
});
console.log(sum);
回答5:
Here's a one liner solution to this problem:
const _ = require('lodash')
let deepFind = (JSONArray, keyPath, keyValue) => _.find(JSONArray, _.matchesProperty(keyPath, keyValue))
let JSONArray = [{a:1, b:2, c:{d: "cd"}}, {a:3, b:4, c:{d: "ef"}}, {a:3, b:4, c:[{d: "ef"}]} ]
console.log(deepFind(JSONArray, "c.d", "cd"))
// {a:1, b:2, c:{d: "cd"}}
console.log(deepFind(JSONArray, "b", 4))
//{a:3, b:4, c:{d: "ef"}}
console.log(deepFind(JSONArray, ['c', 'd'], "cd"))
//{a:1, b:2, c:{d: "cd"}}
console.log(deepFind(JSONArray, 'c[0].d' /* OR ['c', '0', 'd']*/, "ef"))
//{a:1, b:2, c:{d: "cd"}}
来源:https://stackoverflow.com/questions/41610948/lodash-find-deep-in-array-of-object