在Javascript数组中对项目进行分组

时间:2018-04-03 10:47:53

标签: javascript

我有以下数据结构,我试图按其父级别对这些部分进行分组。

  const arr = [
    {
      level: '1.1',
      name: 'group title 1',
    },
    {
      level: '1.1.1',
      name: 'group section 1.1.1',
    },
    {
      level: '1.1.2',
      name: 'group section 1.1.2',
    },
    {
      level: '1.1.3',
      name: 'group section 1.1.3',
    },
    {
      level: '1.2',
      name: 'group title 2',
    },
    {
      level: '1.2.1',
      name: 'group section 1.1.1',
    },
    {
      level: '1.3',
      name: 'group title 3',
    },
    {
      level: '1.3.1',
      name: 'group section 1.1.1',
    },
    {
      level: '1.3.2',
      name: 'group section 1.1.2',
    },
    {
      level: '1.4',
      name: 'group title 4',
    },
    {
      level: '1.4.1',
      name: 'group section 1.4.1',
    },
    {
      level: '1.4.2',
      name: 'group section 1.4.2',
    },
    {
      level: '1.4.3',
      name: 'group section 1.4.3',
    },
  ];

我一直在尝试将结构更改为以下对象(对部分进行分组)。该对象具有父级别的值作为属性和部分的数组。

  const obj = {
    '1.1': [
      {
        level: '1.1.1',
        name: 'group section 1.1.1',
      },
      {
        level: '1.1.2',
        name: 'group section 1.1.2',
      },
      {
        level: '1.1.3',
        name: 'group section 1.1.3',
      },
    ],
    '1.2': [
      {
        level: '1.2',
        name: 'group title 2',
      },
      {
        level: '1.2.1',
        name: 'group section 1.1.1',
      },
    ],
    '1.3': [
      {
        level: '1.3',
        name: 'group title 3',
      },
      {
        level: '1.3.1',
        name: 'group section 1.1.1',
      },
      {
        level: '1.3.2',
        name: 'group section 1.1.2',
      },
    ],
    '1.4': [
      {
        level: '1.4.1',
        name: 'group section 1.4.1',
      },
      {
        level: '1.4.2',
        name: 'group section 1.4.2',
      },
      {
        level: '1.4.3',
        name: 'group section 1.4.3',
      },
    ],
  };

我的尝试没有成功。我将不胜感激如何将结构更改为上述内容。

4 个答案:

答案 0 :(得分:9)

Array.prototype.reduce()可用于从objects构建arrays

String.prototype.match()可用于检测strings中的模式。

/\d+\.\d+/匹配第一次出现的一个或多个numbers后跟一个full stop后跟一个或多个numbers

// Input.
const input = [{level: '1.1',name: 'group title 1',},{level: '1.1.1',name: 'group section 1.1.1',},{level: '1.1.2',name: 'group section 1.1.2',},{level: '1.1.3',name: 'group section 1.1.3',},{level: '1.2',name: 'group title 2',},{level: '1.2.1',name: 'group section 1.1.1',},{level: '1.3',name: 'group title 3',},{level: '1.3.1',name: 'group section 1.1.1',},{level: '1.3.2',name: 'group section 1.1.2',},{level: '1.4',name: 'group title 4',},{level: '1.4.1',name: 'group section 1.4.1',},{level: '1.4.2',name: 'group section 1.4.2',},{level: '1.4.3',name: 'group section 1.4.3',},]

// Group.
const group = (array) => array.reduce((o, x) => {
  const key = x.level.match(/\d+\.\d+/)
  if (o[key]) o[key].push(x)
  else o[key] = [x]
  return o
}, {})

// Output.
const output = group(input)

// Proof.
console.log(output)

答案 1 :(得分:3)

在我看来,遵循DRY原则,更优雅的方式是使用已经具有此功能的Lodash。

const group = arr =>_.groupBy(arr, x => x.level.match(/\d+\.\d+/));
  

_。groupBy https://lodash.com/docs#groupBy

     

创建一个由根据结果生成的键组成的对象   通过iteratee运行集合的每个元素。分组的顺序   值由它们在集合中出现的顺序确定。该   每个键的对应值是一个负责的元素数组   用于生成密钥。

但当然,如果您被允许使用外部库。

结果摘录



const arr = [
    {
      level: '1.1',
      name: 'group title 1',
    },
    {
      level: '1.1.1',
      name: 'group section 1.1.1',
    },
    {
      level: '1.1.2',
      name: 'group section 1.1.2',
    },
    {
      level: '1.1.3',
      name: 'group section 1.1.3',
    },
    {
      level: '1.2',
      name: 'group title 2',
    },
    {
      level: '1.2.1',
      name: 'group section 1.1.1',
    },
    {
      level: '1.3',
      name: 'group title 3',
    },
    {
      level: '1.3.1',
      name: 'group section 1.1.1',
    },
    {
      level: '1.3.2',
      name: 'group section 1.1.2',
    },
    {
      level: '1.4',
      name: 'group title 4',
    },
    {
      level: '1.4.1',
      name: 'group section 1.4.1',
    },
    {
      level: '1.4.2',
      name: 'group section 1.4.2',
    },
    {
      level: '1.4.3',
      name: 'group section 1.4.3',
    },
  ];

const group = arr =>_.groupBy(arr, x => x.level.match(/\d+\.\d+/));

const result = group(arr);

console.log(result);

<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>
&#13;
&#13;
&#13;

在您的问题中,如果您还需要标题(1.1,1.2等),则上述版本包含它们并不清楚。但是如果你不想要它们,你首先需要从阵列中删除它们:

arr.filter(x => !/^\d+\.\d+$/.test(x.level))

一起

const group = arr => {
  const noheaders = arr.filter(x => !/^\d+\.\d+$/.test(x.level));
  return _.groupBy(noheaders, x => x.level.match(/\d+\.\d+/));
}

&#13;
&#13;
const arr = [
    {
      level: '1.1',
      name: 'group title 1',
    },
    {
      level: '1.1.1',
      name: 'group section 1.1.1',
    },
    {
      level: '1.1.2',
      name: 'group section 1.1.2',
    },
    {
      level: '1.1.3',
      name: 'group section 1.1.3',
    },
    {
      level: '1.2',
      name: 'group title 2',
    },
    {
      level: '1.2.1',
      name: 'group section 1.1.1',
    },
    {
      level: '1.3',
      name: 'group title 3',
    },
    {
      level: '1.3.1',
      name: 'group section 1.1.1',
    },
    {
      level: '1.3.2',
      name: 'group section 1.1.2',
    },
    {
      level: '1.4',
      name: 'group title 4',
    },
    {
      level: '1.4.1',
      name: 'group section 1.4.1',
    },
    {
      level: '1.4.2',
      name: 'group section 1.4.2',
    },
    {
      level: '1.4.3',
      name: 'group section 1.4.3',
    },
  ];

const group = arr => {
  const noheaders = arr.filter(x => !/^\d+\.\d+$/.test(x.level));
  return _.groupBy(noheaders, x => x.level.match(/\d+\.\d+/));
}

const result = group(arr);

console.log(result);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>
&#13;
&#13;
&#13;

答案 2 :(得分:0)

  const obj = {};

  for(const {level, name} of array) {
    const key = level.split(".").slice(0, 2).join(".");
    if(obj[key]) {
      obj[key].push({ level, name });
    } else {
      obj[key] = [ { level, name } ];
    }
  }

要了解最新情况,以下页面可能有所帮助:

for ... of

object destructuring

Array#push

答案 3 :(得分:-1)

这是预期输出的简化版本。请检查浏览器控制台中的输出,因此代码段存在问题。谢谢。

&#13;
&#13;
var parent = [];
  var child =[];
  var result =[];

const arr = [
    {
      level: '1.1',
      name: 'group title 1',
    },
    {
      level: '1.1.1',
      name: 'group section 1.1.1',
    },
    {
      level: '1.1.2',
      name: 'group section 1.1.2',
    },
    {
      level: '1.1.3',
      name: 'group section 1.1.3',
    },
    {
      level: '1.2',
      name: 'group title 2',
    },
    {
      level: '1.2.1',
      name: 'group section 1.1.1',
    },
    {
      level: '1.3',
      name: 'group title 3',
    },
    {
      level: '1.3.1',
      name: 'group section 1.1.1',
    },
    {
      level: '1.3.2',
      name: 'group section 1.1.2',
    },
    {
      level: '1.4',
      name: 'group title 4',
    },
    {
      level: '1.4.1',
      name: 'group section 1.4.1',
    },
    {
      level: '1.4.2',
      name: 'group section 1.4.2',
    },
    {
      level: '1.4.3',
      name: 'group section 1.4.3',
    },
  ];

  for(var i=0;i<arr.length;i++){
  if(arr[i].level.length == 3){
 
  parent.push(arr[i]);
  }else{
  child.push(arr[i]);
  }
  }
  
  for(var j=0;j<parent.length;j++){
  result[parent[j].level]=[];
  for(var k=0;k<child.length;k++){
  if(parent[j].level.substring(0, 3)== child[k].level.substring(0, 3)){
   result[parent[j].level].push(child[k]); 
  }
  } 
  }
 console.log(result);
&#13;
&#13;
&#13;