Lodash过滤并删除类似Java流的

时间:2018-07-13 10:13:30

标签: javascript arrays node.js stream lodash

我在使用lodash的nodejs应用程序中有一个树数据结构:

var l = require("lodash");

obj_string = 
`
[
    {
      "father_id": 1,
      "name": "father 1",
      "child_array": [
        {
          "id": 11,
          "name": "father 1 child 1"
        },
        {
          "id": 12,
          "name": "father 1 child 2"
        }
      ]
    },
    {
      "father_id": 2,
      "name": "father 2",
      "child_array": [
        {
          "child_id": 21,
          "name": "father 2 child 1"
        },
        {
          "child_id": 22,
          "name": "father 2 child 2 - TO DELETE"
        }
      ]
    }  
  ]
`;
tree = JSON.parse(obj_string);

我想通过ID删除一个孩子,但我不知道他的父亲是什么

l.chain(tree).flatMap(f=>f.child_array).remove(c=>c.child_id==22);

它不起作用,为什么!?我用过Java流,但不了解lodash是如何工作的。 例如,如果我要搜索一个孩子,并且想要引用已建立的孩子,例如为了编辑其成员(没有_.map),该怎么办?

与此:

ret = l.chain(tree).flatMap(f=>f.child_array).find(c=>c.child_id==22).value();

我在ret中有一个新对象,因此我无法访问/编辑原始对象。 换句话说,第二个问题是:如何从lodash包装器检索对象引用?

4 个答案:

答案 0 :(得分:0)

您可以遍历数组并拒绝child_array中不需要的项目。请注意,这将修改原始对象。

const obj = [{"father_id":1,"name":"father 1","child_array":[{"id":11,"name":"father 1 child 1"},{"id":12,"name":"father 1 child 2"}]},{"father_id":2,"name":"father 2","child_array":[{"child_id":21,"name":"father 2 child 1"},{"child_id":22,"name":"father 2 child 2 - TO DELETE"}]}];

_.forEach(obj, item => {
  item.child_array = _.reject(item.child_array, {child_id: 22});
});

console.log(obj);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>

答案 1 :(得分:0)

恕我直言,您还可以使用Vanilla ES6来实现类似的输出,如下所示:

var arr =[{"father_id":1,"name":"father 1","child_array":[{"id":11,"name":"father 1 child 1"},{"id":12,"name":"father 1 child 2"}]},{"father_id":2,"name":"father 2","child_array":[{"child_id":21,"name":"father 2 child 1"},{"child_id":22,"name":"father 2 child 2 - TO DELETE"}]}];

var newArr = arr.map(obj => {
  return obj.child_array[0].child_id ? 
         (obj.child_array = obj.child_array.filter(c => c.child_id != 22), obj) 
         : obj;
});

console.log(newArr);

答案 2 :(得分:0)

我认为重要的是要认识到lodash的工作原理完全符合您的示例。问题是您做了flatMap(f=>f.child_array),它告诉lodash接受child_array并将其返回到下一个链式操作。接下来,它按预期方式进行操作,删除了与ID匹配的子项,现在剩下的是您通过flatMap的返回请求的子项集合。

似乎您真正想要的是通过fathers映射,删除与ID匹配的子项,然后返回the father

例如,这样做:

var data = [{"father_id":1,"name":"father 1","child_array":[{"id":11,"name":"father 1 child 1"},{"id":12,"name":"father 1 child 2"}]},{"father_id":2,"name":"father 2","child_array":[{"child_id":21,"name":"father 2 child 1"},{"child_id":22,"name":"father 2 child 2 - TO DELETE"}]}];

removeById = (id, data) => _.map(data, father => {
  father.child_array = _.reject(father.child_array, { child_id: id })
  return father
})

console.log(removeById(22, data)) // 2 fathers with 2nd child removed from 2nd father
console.log(removeById(11, data)) // 2 fathers with 1 child each now
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>

答案 3 :(得分:0)

这是使用object-scan的另一个答案。一旦将数据包住头,它对于处理数据斑点非常强大。

这将修改原始对象。

const objectScan = require('object-scan');

const prune = (id, input) => objectScan(['**'], {
  abort: true, // abort after first match
  rtn: 'bool',
  filterFn: ({ value, parent, property }) => {
    if (value.child_id === id) {
      parent.splice(property, 1);
      return true;
    }
    return false;
  }
})(input);

const obj = [{"father_id":1,"name":"father 1","child_array":[{"id":11,"name":"father 1 child 1"},{"id":12,"name":"father 1 child 2"}]},{"father_id":2,"name":"father 2","child_array":[{"child_id":21,"name":"father 2 child 1"},{"child_id":22,"name":"father 2 child 2 - TO DELETE"}]}];

console.log(prune(22, obj)); // returns true iff replacement made
// => true
console.log(JSON.stringify(obj));
// => [{"father_id":1,"name":"father 1","child_array":[{"id":11,"name":"father 1 child 1"},{"id":12,"name":"father 1 child 2"}]},{"father_id":2,"name":"father 2","child_array":[{"child_id":21,"name":"father 2 child 1"}]}]