我有一个包含数组的对象,在这个数组中我想根据类型过滤对象。
我和
.filter
一起工作了。然后我想将这个对象的属性(数组)添加到一个新对象中。
基本上我想要的是按类型过滤子项,并以与
currentElement
相同的结构添加子项。
如果某个项目包含子项目,则该子项目必须添加到与
currentElement
相同结构的对象中。
newElement
就是我想要的结果。
const currentElement = {
items: [
{
name: 'item',
subItems: [
{
name: 'item 1',
type: 'item'
},
{
name: 'item 2',
type: 'item'
}
]
type: 'subItems'
},
{
name: 'item',
type: 'item'
}
]
}
我所期望的:
const newElement= {
items: [
{
name: 'item 1',
type: 'item'
},
{
name: 'item 2',
type: 'item'
}
]
}
过滤子项并映射为新元素。
我尝试过的:
returnItems() {
const items= this.currentElement.items.filter(item => item.type === 'subItems')
.map({subItems}) => subItems);
return items;
}
但这并没有返回我所期望的,这返回了一个Array in Array。虽然我期待类似
newElement
的东西。
我该如何解决这个问题?
最快的方法是
Array::reduce
,无需任何中间数组:
const currentElements = { items: [{ name: 'item', subItems: [{ name: 'item 1', type: 'item' }, { name: 'item 2', type: 'item' } ], type: 'subItems' }, { name: 'item', type: 'item' } ] };
const newElements = {items: currentElements.items.reduce((arr, item) => {
if(item.type === 'subItems'){
arr.push(...item.subItems)
}
return arr;
}, [])};
console.log(newElements);
还有一个基准:
` Chrome/118
---------------------------------------------------------------------------------
reduce (Alexander) 1.00x | x1 30 31 31 33 53
filter and flatMap (a tweak by Alexander) 5.53x | x1 166 174 177 181 204
filter and map (XMehdi01) 5.80x | x1 174 190 203 205 210
flatMap and filter (XMehdi01) 8.23x | x1 247 276 291 307 307
---------------------------------------------------------------------------------
https://github.com/silentmantra/benchmark `
<script benchmark data-count="1">
const elements = { items: []};
const chunk = [{ name: 'item', subItems: [{ name: 'item 1', type: 'item' }, { name: 'item 2', type: 'item' } ], type: 'subItems' }, { name: 'item', type: 'item'}];
let i=1000000; while(i--) elements.items.push(...chunk);
// @benchmark filter and flatMap (a tweak by Alexander)
elements.items.filter(item => item.type === 'subItems')
.flatMap(item => item.subItems);
// @benchmark filter and map (XMehdi01)
elements.items.filter(item => item.type === 'subItems')
.map(item => item.subItems)
.flat();
// @benchmark flatMap and filter (XMehdi01)
elements.items.flatMap(item => item.type == 'subItems' && item.subItems).filter(Boolean)
// @benchmark reduce (Alexander)
elements.items.reduce((arr, item) => {
if(item.type === 'subItems'){
arr.push(...item.subItems)
}
return arr;
}, []);
</script>
<script src="https://cdn.jsdelivr.net/gh/silentmantra/benchmark/loader.js"></script>
将父项包含到结果中的变体:
const currentElements = { items: [{ name: 'item', subItems: [{ name: 'item 1', type: 'item' }, { name: 'item 2', type: 'item' } ], type: 'subItems' }, { name: 'item', type: 'item' } ] };
const newElements = {items: currentElements.items.reduce((arr, item) => {
if(item.type === 'subItems'){
const {subItems, ...parent} = item;
arr.push(...subItems, parent);
}
return arr;
}, [])};
console.log(newElements);
您可以使用
filter
和 map
来完成。
const currentElements = { items: [{ name: 'item', subItems: [{ name: 'item 1', type: 'item' }, { name: 'item 2', type: 'item' } ], type: 'subItems' }, { name: 'item', type: 'item' } ] };
function returnNewElments(elements) {
return {
items: elements.items.filter(item => item.type === 'subItems')
.map(item => item.subItems)
.flat()
}
}
const newElements = returnNewElments(currentElements);
console.log(newElements);
returnItems() {
const items = this.currentElement.items
.filter(item => item.type === 'subItems')
.flatMap(item => item.subItems);
return items;
}
这里的问题是,map 函数返回一个 subItems 数组的数组,这会产生一个数组的数组。相反,您希望将它们“展平”为单个数组。您可以使用 flat 或 flatMap 函数来实现此目的。
代替
map
,您只能使用 Array#flatMap
并检查 item
是否具有属性 subItems
返回其项目。
const currentElements = { items: [{ name: 'item', subItems: [{ name: 'item 1', type: 'item' }, { name: 'item 2', type: 'item' } ], type: 'subItems' }, { name: 'item', type: 'item' } ] };
function returnNewElments(elements) {
return {
items: elements.items.flatMap(item => item.type == 'subItems' && item.subItems).filter(Boolean)
}
}
const newElements = returnNewElments(currentElements);
console.log(newElements);