按数组分组并在主数组中添加字段和子数组

Group by array and add field and sub array in main array

本文关键字:数组 添加 字段      更新时间:2023-09-26

我有一个这样的沉重数组:

[
  {Id: 1, Name: 'Red', optionName: 'Color'}, 
  {Id: 2, Name: 'Yellow', optionName: 'Color'},
  {Id: 3, Name: 'Blue', optionName: 'Color'},
  {Id: 4, Name: 'Green', optionName: 'Color'},
  {Id: 7, Name: 'Black', optionName: 'Color'},
  {Id: 8, Name: 'S', optionName: 'Size'},
  {Id: 11, Name: 'M', optionName: 'Size'},
  {Id: 12, Name: 'L', optionName: 'Size'},
  {Id: 13, Name: 'XL', optionName: 'Size'},
  {Id: 14, Name: 'XXL', optionName: 'Size'}
]

我需要做的是按optionName对它们进行分组,并在主数组中设置两行,如下所示:

[
  {
    Name: 'Color',
    Data:[{Id: 1, Name: 'Red'},
          {Id: 2, Name: 'Yellow'},
          {Id: 3, Name: 'Blue'},
          {Id: 4, Name: 'Green'},
          {Id: 7, Name: 'Black'}]
  }, {
    Name: 'Size',
    Data:[{Id: 8, Name: 'S'},
          {Id: 11, Name: 'M'},
          {Id: 12, Name: 'L'},
          {Id: 13, Name: 'XL'},
          {Id: 14, Name: 'XXL'}]
  }
]

如何在javascript中做到这一点?

这是我

为这种情况写的一个片段。您可以将此功能添加到所有阵列:

Object.defineProperty(Array.prototype, 'group', {
  enumerable: false,
  value: function (key) {
    var map = {};
    this.forEach(function (e) {
      var k = key(e);
      map[k] = map[k] || [];
      map[k].push(e);
    });
    return Object.keys(map).map(function (k) {
      return {key: k, data: map[k]};
    });
  }
});

你可以像这样使用它。您可以只传递一个函数来定义您希望如何对数据进行分组。

var newArray = arr.group(function (item) {
  return item.optionName;
});

工作小提琴

如果需要,可以将{key: k, data: map[k]}替换为 {Name: k, Data: map[k]}


这也是上面代码的更紧凑的 ES6 版本:

Object.defineProperty(Array.prototype, 'group', {
  enumerable: false,
  value: function (key) {
    let map = {};
    this.map(e => ({k: key(e), d: e})).forEach(e => {
      map[e.k] = map[e.k] || [];
      map[e.k].push(e.d);
    });
    return Object.keys(map).map(k => ({key: k, data: map[k]}));
  }
});

像这样使用它:

let newArray = arr.group(item => item.optionName))

使用 Map 对象的 ES6 解决方案:

function groupBy(arr, key) {
  	return arr.reduce(
      (sum, item) => {
      	const groupByVal = item[key];
        groupedItems = sum.get(groupByVal) || [];
        groupedItems.push(item);
      	return sum.set(groupByVal, groupedItems);
        },
      new Map()
      );
}
var Data = [ 
{ Id: 1, Name: 'Red', optionName: 'Color' }, 
  { Id: 2, Name: 'Yellow', optionName: 'Color' },
  { Id: 3, Name: 'Blue', optionName: 'Color' },
  { Id: 4, Name: 'Green', optionName: 'Color' },
  { Id: 7, Name: 'Black', optionName: 'Color' },
  { Id: 8, Name: 'S', optionName: 'Size' },
  { Id: 11, Name: 'M', optionName: 'Size' },
  { Id: 12, Name: 'L', optionName: 'Size' },
  { Id: 13, Name: 'XL', optionName: 'Size' },
  { Id: 14, Name: 'XXL', optionName: 'Size' } ];
document.getElementById("showArray").innerHTML =JSON.stringify([...groupBy(Data, 'optionName')], null, 4); 
<pre id="showArray"></pre>

您可以使用reduce来获取所需的结果集:

var result = list.reduce(function(memo, item) {
  if (item.optionName === 'Color') {
    memo[0].Data.push(
      Id: item.Id,
      Name: item.Name
    });
  }
  if (item.optionName === 'Size') {
    memo[1].Data.push({
      Id: item.Id,
      Name: item.Name
    });
  }
  return memo;
}, [{ Name: 'Color', Data: [] }, { Name: 'Size', Data: [] }]);

变量列表是您的第一个列表。

希望这有帮助。

这是我为所有数组的应用程序功能中的情况编写的一个片段。此代码片段代码用于节点 js 应用程序。以上所有内容都是给定的解决方案,但我在节点js的服务器端发现了一些问题。 这个片段是用户完整的我....

  var Data= [ 
    { Id: 1, Name: 'Red', optionName: 'Color' }, 
      { Id: 2, Name: 'Yellow', optionName: 'Color' },
      { Id: 3, Name: 'Blue', optionName: 'Color' },
      { Id: 4, Name: 'Green', optionName: 'Color' },
      { Id: 7, Name: 'Black', optionName: 'Color' },
      { Id: 8, Name: 'S', optionName: 'Size' },
      { Id: 11, Name: 'M', optionName: 'Size' },
      { Id: 12, Name: 'L', optionName: 'Size' },
      { Id: 13, Name: 'XL', optionName: 'Size' },
      { Id: 14, Name: 'XXL', optionName: 'Size' } ];
    function groupBy(arr, key) {
                var newArr = [],
                    types = {},
                    newItem, i, j, cur;
                for (i = 0, j = arr.length; i < j; i++) {
                    cur = arr[i];
                    if (!(cur[key] in types)) {
                        types[cur[key]] = { type: cur[key], data: [] };
                        newArr.push(types[cur[key]]);
                    }
                    types[cur[key]].data.push(cur);
                }
                return newArr;
}

我是这样用的。我只是传递一个函数来定义您希望如何对数据进行分组。

filterData= groupBy(Data,'optionName');

此代码段输出的结果.....

 [
{"type":"Color","data":[{"Id":1,"Name":"Red","optionName":"Color"},
                       {"Id":2,"Name":"Yellow","optionName":"Color"},
                       {"Id":3,"Name":"Blue","optionName":"Color"}, 
                       {"Id":4,"Name":"Green","optionName":"Color"},
                       {"Id":7,"Name":"Black","optionName":"Color"}]},
{"type":"Size","data":[{"Id":8,"Name":"S","optionName":"Size"},
                       {"Id":11,"Name":"M","optionName":"Size"},
                       {"Id":12,"Name":"L","optionName":"Size"},
                       {"Id":13,"Name":"XL","optionName":"Size"},
                       {"Id":14,"Name":"XXL","optionName":"Size"}]}
]

在小提琴上显示

var originalList = [ { Id: 1, Name: 'Red', optionName: 'Color' }, 
  { Id: 2, Name: 'Yellow', optionName: 'Color' },
  { Id: 3, Name: 'Blue', optionName: 'Color' },
  { Id: 4, Name: 'Green', optionName: 'Color' },
  { Id: 7, Name: 'Black', optionName: 'Color' },
  { Id: 8, Name: 'S', optionName: 'Size' },
  { Id: 11, Name: 'M', optionName: 'Size' },
  { Id: 12, Name: 'L', optionName: 'Size' },
  { Id: 13, Name: 'XL', optionName: 'Size' },
  { Id: 14, Name: 'XXL', optionName: 'Size' } ];
var output = [{ Name: "Color", Data: [] },{ Name: "Size", Data: [] }] ;
originalList.map(function(entry){
    if ( entry.optionName === "Color") output[0].Data.push({ Id: entry.Id, Name: entry.Name });
    if ( entry.optionName === "Size") output[1].Data.push({ Id: entry.Id, Name: entry.Name });
});
'use strict'
let l = [ { Id: 1, Name: 'Red', optionName: 'Color' }, 
          { Id: 2, Name: 'Yellow', optionName: 'Color' },
          { Id: 3, Name: 'Blue', optionName: 'Color' },
  { Id: 4, Name: 'Green', optionName: 'Color' },
  { Id: 7, Name: 'Black', optionName: 'Color' },
  { Id: 8, Name: 'S', optionName: 'Size' },
  { Id: 11, Name: 'M', optionName: 'Size' },
  { Id: 12, Name: 'L', optionName: 'Size' },
  { Id: 13, Name: 'XL', optionName: 'Size' },
  { Id: 14, Name: 'XXL', optionName: 'Size' } ];

let color = [];
let size  = [];
l.forEach(element => {
    if (element['optionName'] === 'Color') {
      color.push({'Id': element.Id, 'Name': element.Name});
    } else {
      size.push({'Id': element.Id, 'Name': element.Name});
    }
});  

console.log(color);
console.log(size);

您可以尝试此方法。

所有的答案都会导致相同的结果,所以这一切都归结为如何解决这个问题的个人偏好(或公司指导方针(。

//  ES5 (traditional javascript) version
function groupByOptionName(list, optionName) {
    return list
        //  filter out any item whose optionName does not match the desired name
        .filter(function(item) {
            return item.optionName === optionName;
        })
        //  map the item into the desired shape 
        //  (appears to be everything except optionName itself
        .map(function(item) {
            return {
                Id: item.Id,
                Name: item.Name
            };
        })
}
//  ES2015/ES6 version
function groupByOptionName(list, optionName) {
    return list
        //  filter out any item whose optionName does not match the desired name
        .filter(item => item.optionName === optionName)
        //  map the item into the desired shape 
        //  (appears to be everything except optionName itself
        .map(item => {
            Id: item.Id,
            Name: item.Name
        });
}

此函数允许您按如下方式对所需结果进行编程:

var output = [
    {Name: 'Color', Data: groupByOptionName(list, 'Color')},
    {Name: 'Size', Data: groupByOptionName(list, 'Size')},
];
//  the ES2015/ES6 version of this code would replace var with let

虽然代码本身不同,但它与其他答案非常相似,只是所需步骤有所不同。

人们也可以选择通过提取这些aswel来省略任何硬编码的选项名称(ColorSize(,这将允许更动态的输入,但也可以引入更多实际需要的处理。

//  ES5 (traditional javascript) version
function getOptionNames(list) {
    return list
        //  map the array into a list of optionNames
        .map(function(item) {
            return item.optionName;
        })
        //  remove duplicates
        .filter(function(item, index, all) {
            return all.indexOf(item) === index;
        });
}
//  ES2015/ES6 version (does exactly the same as the one above)
function getOptionNames(list) {
    return list
        //  map the array into a list of optionNames
        .map(item => item.optionName)
        //  remove duplicates
        .filter((item, index, all) => all.indexOf(item) === index);
}

这允许结果完全基于输入数据:

//  ES5 (traditional javascript) version
var output = getOptionNames(list)
        //  map the names into the desired structure
        .map(function(buffer, name) {
            return {
                Name: name,
                Data: groupByOptionName(list, name)
            };
        });
//  ES2015/ES6 version (does exactly the same as the one above)
var output = getOptionNames(list)
        //  map the names into the desired structure
        .map((buffer, name) => {
            Name: name,
            Data: groupByOptionName(list, name)
        });

通过用简短的简洁步骤编写所有的数据管理步骤,如果需要调整此代码,您将帮助自己(尤其是您未来的自己(。

如果数据集确实很重(就大量数据而言(,您还必须确保将保留在内存中的副本数量限制在内存中。例如,如果您永远不需要原始数据集,请确保可以对其进行垃圾回收(通过在接收数据的范围之外没有包含它的变量(

用法:

groupValues([
    { color: 'blue', value: 100 }, 
    { color: 'blue', value: 75 }, 
    { color: 'yellow', value: 50 },
    { color: 'yellow', value: 25 }
], 'color')

结果:

[
    [{ color: 'blue', value: 100 }, { color: 'blue', value: 75 }],
    [{ color: 'yellow', value: 50 }, { color: 'yellow', value: 25 }] 
]

功能:

const groupValues = function(arr, key) {
    const mapped = {}
    arr.forEach(el => {
        const actualKey = el[key]
        if(!mapped.hasOwnProperty(actualKey)) mapped[actualKey] = []
        mapped[actualKey].push(el)
    })
    return Object.keys(mapped).map(el => mapped[el])
}