[英]Lodash - Find deep in array of object
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
.我需要的是当prop
是foo
时对属性Val
求和。 So, I have to search through elements and get all objects where prop
is foo
.因此,我必须搜索元素并获取prop
为foo
所有对象。 With this objects, I should sum the val
property.有了这个对象,我应该总结val
属性。
I tried to use many combinations of _.find
, _.pick
and so on, but I don't get the right result.我尝试使用_.find
、 _.pick
等的多种组合,但没有得到正确的结果。 Can someone help me?有人能帮我吗?
Here's a solution that flattens the elements and then filters the result to get the required elements before summing the val property:这是一个将元素展平,然后在对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()
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');
I've created library that you can use: https://github.com/dominik791/obj-traverse我已经创建了您可以使用的库: https : //github.com/dominik791/obj-traverse
findAll()
method should solve your problem. findAll()
方法应该可以解决您的问题。 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:然后使用findAll()
方法:
var matchingObjects = findAll( rootObj, 'elements', { 'prop': 'foo' } );
matchingObjects
variable stores all objects with prop
equal to foo
. matchingObjects
变量存储prop
等于foo
所有对象。 And at the end calculate your sum:最后计算你的总和:
var sum = 0;
matchingObjects.forEach(function(obj) {
sum += obj.val;
});
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, "cd", "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"}}
Disclosure: I am the author of that library披露:我是那个图书馆的作者
You can use _.eachDeep method from deepdash:您可以使用deepdash 中的 _.eachDeep方法:
let sum = 0;
_.eachDeep(obj, (value, key, parent) => {
sum += (key == 'prop' && value == 'foo' && parent.val) || 0;
});
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);
here the solution that worked for me if anyone needs it.如果有人需要,这里有对我有用的解决方案。 but my case was a bit different, I needed to find an array that matches the id.但我的情况有点不同,我需要找到一个与 id 匹配的数组。
here a flow function which is not really nesesary but it does make the code easier to read这里有一个流函数,它并不是真正意义上的,但它确实使代码更易于阅读
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
if you dont want to use the flow function it can also be done like that I think I didnt test the code but it should work如果您不想使用流功能,也可以这样做,我想我没有测试代码,但它应该可以工作
const results = _.find(_.flatten(_.map(arr, 'elements')), { val: 65 });
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.