如何在JavaScript / Jquery中按数组分组

时间:2019-02-24 21:49:21

标签: javascript jquery

我有一个如下数组

array1 = [{"month":"January","location":"CENTRAL","percentage":94},
{"month":"February","location":"CENTRAL","percentage":97},
{"month":"March","location":"CENTRAL","percentage":93},
{"month":"January","location":"NORTH","percentage":95},
{"month":"February","location":"NORTH","percentage":91},
{"month":"March","location":"NORTH","percentage":98}];

我想格式化数组,使其如下所示

array2= [{
    location: "CENTRAL",
    January: 94,
    February: 97,
    March: 93},
    {
    location: "NORTH",
    January: 95,
    February: 91,
    March: 98}];

我试图按以下功能使用分组功能

function groupBy(list, keyGetter) {
    const map = new Map();
    list.forEach((item) => {
        const key = keyGetter(item);
        if (!map.has(key)) {
            map.set(key, [item]);
        } else {
            map.get(key).push(item);
        }
    });
    return map;
}

const grouped = groupBy(array1, arr => arr.location);
console.log(grouped);

但是我没有得到相同的格式。有什么建议可以帮助我解决我的想法吗?非常感谢。

6 个答案:

答案 0 :(得分:3)

您确实可以使用按位置作为键的地图,但是可以将普通对象用作值。代码中的问题是,您将项目推入数组,并且不将month值转换为单个对象的属性(按位置)。

因此,给定一个包含普通对象的地图,请迭代输入,并将月属性插入具有相应百分比值的那些普通对象中,然后获取该地图的值:

const array1 = [{"month":"January","location":"CENTRAL","percentage":94},{"month":"February","location":"CENTRAL","percentage":97},{"month":"March","location":"CENTRAL","percentage":93},{"month":"January","location":"NORTH","percentage":95},{"month":"February","location":"NORTH","percentage":91},{"month":"March","location":"NORTH","percentage":98}];

const map = new Map(array1.map(({location}) => [location, { location }]));
array1.forEach(o => map.get(o.location)[o.month] = o.percentage);
const result = [...map.values()];

console.log(result);

答案 1 :(得分:3)

一种替代方法是使用函数reducelocation进行分组,并使用函数Object.values提取分组的对象。

let array1 = [{"month":"January","location":"CENTRAL","percentage":94},{"month":"February","location":"CENTRAL","percentage":97},{"month":"March","location":"CENTRAL","percentage":93},{"month":"January","location":"NORTH","percentage":95},{"month":"February","location":"NORTH","percentage":91},{"month":"March","location":"NORTH","percentage":98}],
    groupBy = (array, keygetter) => {
      return Object.values(array1.reduce((a, {month, percentage, ...rest}) => {
        let key = keygetter(rest);
        (a[key] || (a[key] = {location: key}))[month] = percentage;
        return a;
      }, Object.create(null)));
    },
    result = groupBy(array1, (o) => o.location);
    
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 2 :(得分:2)

您可以通过传递组密钥,密钥和收集值来使用动态方法。

然后将所有键/值对添加到对象,然后返回映射的值。

function groupBy(list, group, key, value) {
    return Array.from(list
        .reduce((map, object) => map.set(object[group], Object.assign(
            map.get(object[group]) || { [group]: object[group] },
            { [object[key]]: object[value] }
        )), new Map)
        .values()
    );
}

var array = [{ month: "January", location: "CENTRAL", percentage: 94 }, { month: "February", location: "CENTRAL", percentage: 97 }, { month: "March", location: "CENTRAL", percentage: 93 }, { month: "January", location: "NORTH", percentage: 95 }, { month: "February", location: "NORTH", percentage: 91 }, { month: "March", location: "NORTH", percentage: 98 }],
    result = groupBy(array, 'location', 'month', 'percentage');

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 3 :(得分:2)

一种方法是使用.filter().map()

var array1 = [{"month":"January","location":"CENTRAL","percentage":94},
{"month":"February","location":"CENTRAL","percentage":97},
{"month":"March","location":"CENTRAL","percentage":93},
{"month":"January","location":"NORTH","percentage":95},
{"month":"February","location":"NORTH","percentage":91},
{"month":"March","location":"NORTH","percentage":98}];

const groupBy = (arr, prop, propName1, propName2, propName3) => 
  Object.assign({[prop]:propName1}
  , ...arr.filter(({[prop]:p}) => p === propName1)
    .map(({[propName2]:m, [propName3]:p}) => ({[m]: p}))
  );

const locations = ["CENTRAL", "NORTH"];

let res = locations.map(prop => groupBy(array1, "location", prop, "month", "percentage"));

console.log(res);

答案 4 :(得分:0)

问题是,您不能只是重新排列对象中的属性。根据{{​​3}}:

  

ECMAScript 对象是{strong>属性

unordered集合

您可以使用函数重新排列属性,但是不能保证最终对象中的顺序。

答案 5 :(得分:0)

这是另一个使用reduce的示例,传递回调函数并在其中指定键

array1 = [{
    "month": "January",
    "location": "CENTRAL",
    "percentage": 94
  },
  {
    "month": "February",
    "location": "CENTRAL",
    "percentage": 97
  },
  {
    "month": "March",
    "location": "CENTRAL",
    "percentage": 93
  },
  {
    "month": "January",
    "location": "NORTH",
    "percentage": 95
  },
  {
    "month": "February",
    "location": "NORTH",
    "percentage": 91
  },
  {
    "month": "March",
    "location": "NORTH",
    "percentage": 98
  }
];


function groupBy(list, callback) {
  return list.reduce((acc, x) => {
    const key = callback(x);
    if (!acc[key]) {
      return {
        ...acc,
        [key]: [x]
      }
    }
    return {
      ...acc,
      [key]: [...acc[key], x]
    }

  }, {})
}

// callback function
function locationName(obj) {
  return obj.location
}


console.log('group by location name:', groupBy(array1, locationName));