【问题标题】:deep flatten all items in collection using lodash使用 lodash 深度展平集合中的所有项目
【发布时间】:2017-01-10 21:37:44
【问题描述】:

我希望展平如下所示的数组:

[{
    "id": 0,
    "text": "item 0"
}, {
    "id": 1,
    "items": [{
        "id": 2,
        "text": "item 2"
    }, {
        "id": 3,
        "items": [{
            "id": 4,
            "text": "item 4"
        }]
    }]
}]

进入这个

[{
    "id": 0,
    "text": "item 0"
}, {
    "id": 2,
    "text": "item 2"
}, {
    "id": 4,
    "text": "item 4"
}]

基本上保留所有没有“items”属性的元素,如果有,则递归遍历所有“items”数组。

我确实可以编写一个递归函数,但我正在寻找一种漂亮的 lodash 或下划线方法来解决这个问题。

【问题讨论】:

  • 技术上递归是函数式方法...
  • 您的数据无效
  • 递归好看。

标签: javascript underscore.js lodash flatten flatmap


【解决方案1】:

在 lodash 或下划线中没有简洁的功能。我认为递归函数是你最好的选择:

function collect(array, result) {
  array.forEach(function(el) {
    if(el.items) {
      collect(el.items, result);
    } else {
      result.push(el);
    }
  });
}

var array = [{
    "id": 0,
    "text": "item 0"
}, {
    "id": 1,
    "items": [{
        "id": 2,
        "text": "item 2"
    }, {
        "id": 3,
        "items": [{
            "id": 4,
            "text": "item 4"
        }]
    }]
}];

function collect(array, result) {
  array.forEach(function(el) {
    if(el.items) {
      collect(el.items, result);
    } else {
      result.push(el);
    }
  });
}
var result = [];
collect(array, result);
console.log(result);

【讨论】:

  • 现在有 _.flatMapDeep() 递归地展平集合。
  • @Nice-Guy _.flatMapDeep() 只是_.map().flattenDeep() 的一个捷径并且不递归迭代任何子节点是不正确的
【解决方案2】:

今天遇到了这个,很惊讶 lodash flatMapDeep 不适合这个。这是我编写的一个简单的递归函数,它可以满足您的期望,同时还允许您进行映射。

function flattenTree(items, callback, nestingKey = 'items') {
    let output = []

    items.forEach(item => {
        output.push(callback ? callback(item) : item)
        output = output.concat(flattenTree(item[nestingKey] || [], callback, nestingKey))
    })

    return output
}
  • 第一个参数是你的树形结构
  • 第二个参数是一个可选的回调函数,用于控制您希望如何映射结果
  • 如果树中的嵌套键不是items,则可以使用第三个参数

您的用例的示例用法:

let output = flattenTree(items, item => ({
    id: item.id,
    text: item.text
}))

仅提取ID 字段的示例:

let ids = flattenTree(items, item => item.id)

【讨论】:

    【解决方案3】:

    也可以使用原生的flatMap函数:

    const tree = [{
        "id": 0,
        "text": "item 0"
    }, {
        "id": 1,
        "items": [{
            "id": 2,
            "text": "item 2"
        }, {
            "id": 3,
            "items": [{
                "id": 4,
                "text": "item 4"
            }]
        }]
    }]
    
    function flattenTree(tree){
       return tree.flatMap( item => item.items ? [item, ...flattenTree(item.items)] : item);
    }
    
    
    flattenTree(tree);
    

    如果你想删除道具“项目”,你可以这样做:

    const tree = [{
        "id": 0,
        "text": "item 0"
    }, {
        "id": 1,
        "items": [{
            "id": 2,
            "text": "item 2"
        }, {
            "id": 3,
            "items": [{
                "id": 4,
                "text": "item 4"
            }]
        }]
    }]
    
    
    function flattenTreeNoItems(tree){
       return tree.flatMap( item => {
        if(item.items){
          const items = item.items;
          delete item.items;
          return [item, ...flattenTreeNoItems(items)];
            }
        return item;
       });
    }
    
    flattenTreeNoItems(tree);
    

    【讨论】:

      【解决方案4】:

      lodash/flattenDeep 将递归地展平一个数组。例如:

      import {flattenDeep} from 'lodash'
      const nestedArray = [1, ['2', [3, [{x: 4}]]]]
      const mixedNestedArray = [1, ['2', [3, [{x: [[4]]}]]]]
      
      console.log(flattenDeep(nestedArray)) // [1, '2', 3, {x: 4}]
      console.log(flattenDeep(mixedNestedArray)) // [1, '2', 3, {x: [[4]]}]

      请注意,对象内的嵌套数组不会受到影响,这是您所期望的。

      【讨论】:

        【解决方案5】:

        两行代码的可能解决方案,使用lodash/flatMap

        const iteratee = item => (item.items ? _.flatMap(item.items, iteratee) : item);
        const flattenedItems = _.flatMap(sourceItems, iteratee);
        

        写在我的头上,所以用一粒盐来对待它。

        【讨论】:

        • 你有一个香草 JS 版本和一个使用 flattenDeep 的 lodash 版本。我不确定 flatMap 会带来什么其他人在这篇 4 年前的帖子中尚未涵盖的内容。
        • 确认,警官@hppycoder!我永远不会再在旧帖子上发布任何新发现或想法。
        猜你喜欢
        • 2016-04-11
        • 2017-01-07
        • 1970-01-01
        • 2021-07-01
        • 2013-12-07
        • 1970-01-01
        • 2021-08-02
        • 2020-09-05
        相关资源
        最近更新 更多