【问题标题】:Lodash filter and remove like java streamsLodash 过滤和删除类似 java 流
【发布时间】:2023-03-31 15:50:01
【问题描述】:

我在使用 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 包装器中检索对象引用?

【问题讨论】:

  • 也许你可以试试highlandjs.org 它可以让你使用流和背压
  • 我看看,谢谢
  • @Salvo 你是从字符串中解析的吗?然后您必须更新已解析的(原始)对象(删除带有 id 的子对象)?那么有更好的解决方案!

标签: javascript arrays node.js stream lodash


【解决方案1】:

这是使用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(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' } ] } ]
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/object-scan@13.8.0"></script>

免责声明:我是object-scan的作者

【讨论】:

    【解决方案2】:

    我认为重要的是要意识到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】:

      恕我直言,您也可以使用 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);

      【讨论】:

        【解决方案4】:

        您可以遍历数组并拒绝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>

        【讨论】:

        • 这不太容易适用,在原始数据结构中我有一个很大很深的树结构,但是谢谢
        猜你喜欢
        • 2017-01-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-08
        • 1970-01-01
        • 2021-12-14
        • 1970-01-01
        相关资源
        最近更新 更多