如何在新的数据模型中过滤和映射嵌套数组?

问题描述 投票:0回答:4

我有一个包含数组的对象,在这个数组中我想根据类型过滤对象。

我和

.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
的东西。

我该如何解决这个问题?

javascript arrays ecmascript-6
4个回答
2
投票

最快的方法是

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


2
投票

您可以使用

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


1
投票
returnItems() {
  const items = this.currentElement.items
    .filter(item => item.type === 'subItems')
    .flatMap(item => item.subItems);
    
  return items;
}

这里的问题是,map 函数返回一个 subItems 数组的数组,这会产生一个数组的数组。相反,您希望将它们“展平”为单个数组。您可以使用 flat 或 flatMap 函数来实现此目的。


1
投票

代替

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

© www.soinside.com 2019 - 2024. All rights reserved.