按两个属性对对象数组进行分组

huangapple go评论68阅读模式
英文:

Group array of objects by two properties

问题

我尝试通过两个属性将对象数组分组,以便在两个级别获取数据。这是在JavaScript - Node服务器中进行的操作。这是我要处理的数据:

items = [
  {month: 11, year: 2022, amount: 10},
  {month: 12, year: 2022, amount: 6},
  {month: 11, year: 2022, amount: 7},
  {month: 12, year: 2022, amount: 12},
  {month: 1, year: 2023, amount: 5},
  {month: 1, year: 2023, amount: 15},
  {month: 11, year: 2023, amount: 30},
  {month: 11, year: 2023, amount: 20}
]

我需要将同一年和同一月的所有项目分组在一起。最终结果将如下所示:

result = {
  "2022": {
    "11": [
      {month: 11, year: 2022, amount: 10},
      {month: 11, year: 2022, amount: 7}
    ],
    "12": [
      {month: 12, year: 2022, amount: 6},
      {month: 12, year: 2022, amount: 12}
    ]
  },
  "2023": {
    "11": [
      {month: 11, year: 2023, amount: 30},
      {month: 11, year: 2023, amount: 20}
    ],
    "1": [
      {month: 1, year: 2023, amount: 5},
      {month: 1, year: 2023, amount: 15}
    ]
  }
}

第一步很容易完成,可以使用reduce或groupBy(),我选择了groupBy()因为它更清晰:

const itemsPerYear = items.groupBy(item => { return item.year })

这给我一个中间结果:

itemsPerYear = {
  "2022": [
      {month: 11, year: 2022, amount: 10},
      {month: 11, year: 2022, amount: 7},
      {month: 12, year: 2022, amount: 6},
      {month: 12, year: 2022, amount: 12}
    ],
  "2023": [
      {month: 11, year: 2023, amount: 30},
      {month: 11, year: 2023, amount: 20},
      {month: 1, year: 2023, amount: 5},
      {month: 1, year: 2023, amount: 15}
    ]
}

所以,如果我应用类似的逻辑并执行:

const itemsPerMonth = Object.values(itemsPerYear).groupBy(item => { return item.month })

我得到以下结果:

[Object: null prototype] {
  undefined: [
    [ [Object], [Object], [Object], [Object] ],
    [ [Object], [Object], [Object], [Object] ]
  ]
}

通过使用forEach(),我离目标更近一步:

const itemsPerMonth = Object.values(itemsPerYear).forEach(sub => { console.log(sub) })

这给我:

[
    {month: 11, year: 2022, amount: 10},
    {month: 11, year: 2022, amount: 7},
    {month: 12, year: 2022, amount: 6},
    {month: 12, year: 2022, amount: 12}
],
[
    {month: 11, year: 2023, amount: 30},
    {month: 11, year: 2023, amount: 20},
    {month: 1, year: 2023, amount: 5},
    {month: 1, year: 2023, amount: 15}
]

如果我想在forEach()内部使用groupBy(),我得到undefined。

谢谢。

英文:

I'm trying to group array of objects by two properties so I get data on two levels. This is in JavaScript - Node server.
Here is the data I'm starting with

items = [
  {month: 11, year: 2022, amount: 10},
  {month: 12, year: 2022, amount: 6},
  {month: 11, year: 2022, amount: 7},
  {month: 12, year: 2022, amount: 12},
  {month: 1, year: 2023, amount: 5},
  {month: 1, year: 2023, amount: 15},
  {month: 11, year: 2023, amount: 30},
  {month: 11, year: 2023, amount: 20}
],

I need all items from the same month and in the same year grouped together. The final result would look like this:

result = {
  "2022": {
    "11": [
      {month: 11, year: 2022, amount: 10},
      {month: 11, year: 2022, amount: 7}
    ],
    "12": [
      {month: 12, year: 2022, amount: 6},
      {month: 12, year: 2022, amount: 12}
    ]
  },
  "2023": {
    "11": [
      {month: 11, year: 2023, amount: 30},
      {month: 11, year: 2023, amount: 20}
    ],
    "1": [
      {month: 1, year: 2023, amount: 5},
      {month: 1, year: 2023, amount: 15}
    ]
  }
}

The first step is done quite easily, either through reduce or groupBy(), I've opted for groupBy() because it is cleaner:

const itemsPerYear = items.groupBy(item => { return item.year })

This gives me intermediate result:

itemsPerYear = {
  "2022": [
      {month: 11, year: 2022, amount: 10},
      {month: 11, year: 2022, amount: 7},
      {month: 12, year: 2022, amount: 6},
      {month: 12, year: 2022, amount: 12}
    ],
  "2023": [
      {month: 11, year: 2023, amount: 30},
      {month: 11, year: 2023, amount: 20},
      {month: 1, year: 2023, amount: 5},
      {month: 1, year: 2023, amount: 15}
    ]
}

So if I apply similar logic and go with:

const itemsPerMonth = Object.values(itemsPerYear).groupBy(item => { return item.month })

I get:

[Object: null prototype] {
  undefined: [
    [ [Object], [Object], [Object], [Object] ],
    [ [Object], [Object], [Object], [Object] ]
  ]
}

I get a step closer with ForEach:
const itemsPerMonth = Object.values(itemsPerYear).forEach(sub => { console.log(sub) })
I get:

[
    {month: 11, year: 2022, amount: 10},
    {month: 11, year: 2022, amount: 7},
    {month: 12, year: 2022, amount: 6},
    {month: 12, year: 2022, amount: 12}
],
[
    {month: 11, year: 2023, amount: 30},
    {month: 11, year: 2023, amount: 20},
    {month: 1, year: 2023, amount: 5},
    {month: 1, year: 2023, amount: 15}
]

If I want to use groupBy() inside the ForEach() I get undefined.

Thanks

答案1

得分: 4

以下是使用.reduce()的快速解决方案:

const input = [ {month: 11, year: 2022, amount: 10}, {month: 12, year: 2022, amount: 6}, {month: 11, year: 2022, amount: 7}, {month: 12, year: 2022, amount: 12}, {month: 1, year: 2023, amount: 5}, {month: 1, year: 2023, amount: 15}, {month: 11, year: 2023, amount: 30}, {month: 11, year: 2023, amount: 20} ];

const result = input.reduce((acc, obj) => {
  if(!acc[obj.year]) acc[obj.year] = {};
  if(!acc[obj.year][obj.month]) acc[obj.year][obj.month] = [];
  acc[obj.year][obj.month].push(obj);
  return acc;
}, {});
console.log('result:', result);

文档:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce

英文:

Here is a quick solution using a .reduce():

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const input = [ {month: 11, year: 2022, amount: 10}, {month: 12, year: 2022, amount: 6}, {month: 11, year: 2022, amount: 7}, {month: 12, year: 2022, amount: 12}, {month: 1, year: 2023, amount: 5}, {month: 1, year: 2023, amount: 15}, {month: 11, year: 2023, amount: 30}, {month: 11, year: 2023, amount: 20} ];

const result = input.reduce((acc, obj) =&gt; {
  if(!acc[obj.year]) acc[obj.year] = {};
  if(!acc[obj.year][obj.month]) acc[obj.year][obj.month] = [];
  acc[obj.year][obj.month].push(obj);
  return acc;
}, {});
console.log(&#39;result:&#39;, result);

<!-- end snippet -->

Docs: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce

huangapple
  • 本文由 发表于 2023年2月6日 07:07:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/75356124.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定