我有一个像这样的对象数组
[
{
'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
}
]
},
]
我需要的是在Val
为prop
时对属性foo
求和。
因此,我必须搜索元素并获取prop
为foo
的所有对象。有了这个对象,我应该总结val
属性。
我尝试使用_.find
,_.pick
等许多组合,但我没有得到正确的结果。有人能帮助我吗?
答案 0 :(得分:14)
这是一个解决方案,flattens元素,然后filters结果,以便在summing val属性之前获取所需的元素:
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()
链接是一种在返回值之前将一系列操作应用于某些数据的方法。上面的示例使用显式链接,但可能(可能应该)使用隐式链接编写:
var result = _(data)
.map('elements')
.flatten()
.filter({prop: 'foo'})
.sumBy('val');
答案 1 :(得分:4)
我已经创建了您可以使用的库:https://github.com/dominik791/obj-traverse
findAll()
方法应该可以解决您的问题。第一个参数是根对象,而不是数组,因此您应该首先创建它:
var rootObj = {
name: 'rootObject',
elements: [
{
'a': 10,
elements: [ ... ]
},
{
'b': 50,
elements: [ ... ]
}
]
};
然后使用findAll()
方法:
var matchingObjects = findAll( rootObj, 'elements', { 'prop': 'foo' } );
matchingObjects
变量存储prop
等于foo
的所有对象。并在最后计算你的总和:
var sum = 0;
matchingObjects.forEach(function(obj) {
sum += obj.val;
});
答案 2 :(得分:1)
您可以使用deepdash中的_.eachDeep方法:
let sum = 0;
_.eachDeep(obj, (value, key, parent) => {
sum += (key == 'prop' && value == 'foo' && parent.val) || 0;
});
这是您的案件的example
答案 3 :(得分:0)
你可以遍历数据并得到总和。试试这个:
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);
使用过滤器:
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);
答案 4 :(得分:0)
这是一个解决此问题的方法:
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"}}
答案 5 :(得分:0)
这里有对我有用的解决方案,如果有人需要的话。但我的情况有点不同,我需要找到一个与 id 匹配的数组。
这里有一个流函数,它并不是真正必要的,但它确实使代码更易于阅读
const flow = functions => data =>
functions.reduce((value, func) => func(value), data);
const 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
}
]
},
]
const result= _.flow([
data => _.map(data, 'elements'), // get all elements from the array
data => _.flatten(data), // create a singler array
data => _.find(data, { val: 65 }) // find the needed value in array
// you can keep on adding logic here depending on your need
])(arr); // the inital array
如果你不想使用流功能,我认为也可以这样做 我没有测试代码,但它应该可以工作
const results = _.find(_.flatten(_.map(arr, 'elements')), { val: 65 });