使用 lodash 深度展平集合中的所有项目

deep flatten all items in collection using lodash

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

[{
    "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 或下划线方法来解决这个问题。

在 lodash 或 underscore 中没有针对此的简洁函数。我认为递归函数是你最好的选择:

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);

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]]}]

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

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

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

写在我的头顶上,所以对它持保留态度。

今天遇到这个问题,很惊讶 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)

您还可以使用本机 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);