首页 > 解决方案 > JavaScript 将平面数组转换为嵌套/分组和排序数组

问题描述

我正在尝试将对象数组转换为 JavaScript 中的“分组”和排序的输出数组,最好是 ES6 方式(例如使用.map,.reduce等)。

概括:

const data = [
    { section: 'A', item: 'a1', section_order: 2, item_order: 2 },
    { section: 'B', item: 'b1', section_order: 1, item_order: 2 },
    { section: 'A', item: 'a2', section_order: 2, item_order: 1 },
    { section: 'B', item: 'b2', section_order: 1, item_order: 1 }
];


const desiredOutput = [
    {
        section: 'B',  // should come first as section_order = 1
        items: [
            { section: 'B', item: 'b2', section_order: 1, item_order: 1 },  // should come first as item_order = 1
            { section: 'B', item: 'b1', section_order: 1, item_order: 2 },   // should come second as item_order = 2
        ]
    },
    {
        section: 'A',   // should come second as section_order = 2
        items: [
            { section: 'A', item: 'a2', section_order: 2, item_order: 1 },
            { section: 'A', item: 'a1', section_order: 2, item_order: 2 },
        ]
    }
];

我看到了一个例子,它让我朝着正确的方向前进——但并不完全符合所需的输出,也没有满足排序顺序:

const result = data.reduce((accum, currElm) => {
    const currSection = currElm['section'];
    accum[currSection] = (accum[currSection] || []).concat(currElm);
    return accum;
}, {});

标签: javascriptarraysobjectecmascript-6transform

解决方案


您应该sort首先使用您的数据。sort函数看起来像这样

data.sort((a, b) => (a.section_order - b.section_order) || (a.item_order - b.item_order));

如您所见,我们将条件分为两部分:

  1. (a.section_order - b.section_order)
  2. (a.item_order - b.item_order)

这意味着您section_order按排序item_order

之后,您可以使用字典功能循环一次,如下所示

const data = [
    { section: 'A', item: 'a1', section_order: 2, item_order: 2 },
    { section: 'B', item: 'b1', section_order: 1, item_order: 2 },
    { section: 'A', item: 'a2', section_order: 2, item_order: 1 },
    { section: 'B', item: 'b2', section_order: 1, item_order: 1 }
];
data.sort((a, b) => (a.section_order - b.section_order) || (a.item_order - b.item_order));

var result = [];
for(var item of data){
  var section = item.section;
  if(!result[section]){ // if not exists => create new 
    result[section] = { section, items:[item] };
  }else{ // if exists => add one more item into items 
   result[section].items.push(item);
  }
}
console.log(Object.values(result));

旧版本使用reduce & map

const data = [
    { section: 'A', item: 'a1', section_order: 2, item_order: 2 },
    { section: 'B', item: 'b1', section_order: 1, item_order: 2 },
    { section: 'A', item: 'a2', section_order: 2, item_order: 1 },
    { section: 'B', item: 'b2', section_order: 1, item_order: 1 }
];
data.sort((a, b) => (a.section_order - b.section_order) || (a.item_order - b.item_order));

const accumData = data.reduce((accum, currElm) => {
    const currSection = currElm['section'];
    accum[currSection] = (accum[currSection] || []).concat(currElm);
    return accum;
}, {}); 


var result = Object.entries(accumData).map(([key, value]) => ({section: key, items: value}));
console.log(result);


推荐阅读