使用 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);
我希望展平如下所示的数组:
[{
"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);