typescript 如何在属性中按子属性分组?

gudnpqoy  于 2022-12-14  发布在  TypeScript
关注(0)|答案(1)|浏览(150)

我得到了一个包含多个键对象,它包含一个值数组。在这个数组中,有一个嵌套的值,我想在保留主键的同时,根据它进行分组。
所以在我的数据中我得到了:

{
  "foo1": [
    {
      "name": "foo1",
      "subpart": {
        "part": "bar1"
      }
    },
    {
      "name": "foo1",
      "subpart": {
        "part": "bar1"
      }
    },
    {
      "name": "foo1",
      "subpart": {
        "part": "bar2"
      }
    },
    {
      "name": "foo1",
      "subpart": {
        "part": "bar2"
      }
    },
    {
      "name": "foo1",
      "subpart": {
        "part": "bar3"
      }
    },
    {
      "name": "foo1",
      "subpart": {
        "part": "bar3"
      }
    }
  ],
  "foo2": [
    {
      "name": "foo2",
      "subpart": {
        "part": "bar1"
      }
    },
    {
      "name": "foo2",
      "subpart": {
        "part": "bar1"
      }
    },
    {
      "name": "foo2",
      "subpart": {
        "part": "bar2"
      }
    },
    {
      "name": "foo2",
      "subpart": {
        "part": "bar3"
      }
    },
    {
      "name": "foo2",
      "subpart": {
        "part": "bar3"
      }
    }
  ]
}

我希望它变成:

{
  "foo1": {
    "bar1": [
      {
        "name": "foo1",
        "subpart": {
          "part": "bar1"
        }
      },
      {
        "name": "foo1",
        "subpart": {
          "part": "bar1"
        }
      }
    ],
    "bar2": [
      {
        "name": "foo1",
        "subpart": {
          "part": "bar2"
        }
      },
      {
        "name": "foo1",
        "subpart": {
          "part": "bar2"
        }
      }
    ],
    "bar3": [
      {
        "name": "foo1",
        "subpart": {
          "part": "bar3"
        }
      },
      {
        "name": "foo1",
        "subpart": {
          "part": "bar3"
        }
      }
    ]
  },
  "foo2": {
    "bar1": [
      {
        "name": "foo2",
        "subpart": {
          "part": "bar1"
        }
      },
      {
        "name": "foo2",
        "subpart": {
          "part": "bar1"
        }
      }
    ],
    "bar2": [
      {
        "name": "foo2",
        "subpart": {
          "part": "bar2"
        }
      }
    ],
    "bar3": [
      {
        "name": "foo2",
        "subpart": {
          "part": "bar3"
        }
      },
      {
        "name": "foo2",
        "subpart": {
          "part": "bar3"
        }
      }
    ]
  }
}

现在我已经找到了一些例子,但这只在一个级别上进行分组,其中“key”是第一个组,但我在某个子值中得到了第二个属性,作为分组的第二个级别(如果这有意义的话)。
目前为止我最好的回答是:

function groupBy<T>(arr: T[], fn: (item: T) => any) {
  return arr.reduce<Record<string, T[]>>((prev, curr) => {
      const groupKey = fn(curr);
      const group = prev[groupKey] || [];
      group.push(curr);
      return { ...prev, [groupKey]: group };
  }, {});
}

然后:

const grouped = groupBy(data, (x) => x.subpart.part)

但这样就把它组合成了一个主键,我不想要。

fnvucqvd

fnvucqvd1#

实际上,您需要将groupByMap到数据中的每个值。
在TypeScript中Map对象有些困难/不直接。您可以先使用Object.entriesObject.fromEntries将对象转换为数组,然后Map它,再将它转换回对象。但是,这样做会破坏类型推断,并使结果为any类型。因此,在需要这样做时要小心,同时还要维护类型安全。
您可能也要考虑重构程式码,以便将数组架构的结构当做此转换的输入和/或输出使用,因为它更容易使用,也更容易维护类型安全。

const data = { "foo1": [...], ...}

const dataArr = Object.entries(data);
const mappedArr = dataArr.map(([k,v]) => [k, groupBy(v, (x) => x.subpart.part)]);
const result = Object.fromEntries(mappedArr);

TSPlayground

相关问题