Lodash - 深入查找对象数组

Mis*_*e83 10 javascript lodash

我有一个像这样的对象数组

[
    {
        '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
            }
        ]
    },
]
Run Code Online (Sandbox Code Playgroud)

我需要的是总结的财产Val时,propfoo.所以,我要通过要素进行搜索,并得到所有的对象,其中propfoo.有了这个对象,我应该总结一下这个val属性.

我试图使用许多组合_.find,_.pick等等,但我没有得到正确的结果.有人能帮我吗?

Gru*_*nny 16

这是一个解决方案,它使元素变平,然后在求和 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()
Run Code Online (Sandbox Code Playgroud)

链接是一种在返回值之前将一系列操作应用于某些数据的方法.上面的示例使用显式链接但可能(可能应该)使用隐式链接编写:

var result = _(data)
    .map('elements')
    .flatten()
    .filter({prop: 'foo'})
    .sumBy('val');
Run Code Online (Sandbox Code Playgroud)

  • 似乎是一个完美的解决方案,但是为了更好地理解该解决方案的未来用法,请在每种方法之后解释结果。 (2认同)

dom*_*791 5

我创建了您可以使用的库:https ://github.com/dominik791/obj-traverse

findAll()方法应该可以解决你的问题。第一个参数是根对象,而不是数组,因此您应该首先创建它:

var rootObj = {
  name: 'rootObject',
  elements: [
    {
      'a': 10,
       elements: [ ... ]
    },
    {
       'b': 50,
       elements: [ ... ]
    }
  ]
};
Run Code Online (Sandbox Code Playgroud)

然后使用findAll()方法:

var matchingObjects = findAll( rootObj, 'elements', { 'prop': 'foo' } );
Run Code Online (Sandbox Code Playgroud)

matchingObjects变量存储所有prop等于 的对象foo。最后计算你的总和:

var sum = 0;
matchingObjects.forEach(function(obj) {
  sum += obj.val;
});
Run Code Online (Sandbox Code Playgroud)


小智 5

这是解决此问题的单行解决方案:

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"}}
Run Code Online (Sandbox Code Playgroud)