【问题标题】:Group data in array of TypeScript objects to different array of objects将 TypeScript 对象数组中的数据分组到不同的对象数组
【发布时间】:2018-11-25 16:47:44
【问题描述】:

在 TypeScript 中,假设我有一个 Person 对象数组。

我们有一个名为 myPersons 的数组:

[
 {'age': '25', 'name': 'mike'},
 {'age': '25', 'name': 'john'},
 {'age': '25', 'name': 'charles'},
 {'age': '30', 'name': 'melanie'},
 {'age': '30', 'name': 'cindy'}
]

我想使用 Lodash 或一些不那么混乱的方法来解析这个数组,以获取一个对象数组,其中 Object 有一个键 'age' 映射到一个字符串和一个键 'names' 映射到一个字符串数组。

所以最终生成的数组如下所示:

[
 {'age': '25', 'names': ['john', 'mike', 'charles']},
 {'age': '30', 'names': ['cindy', 'melanie']}
]

我可以使用一些混乱的 for 循环来完成上述操作,但我是前端开发的新手,我感觉这不是最好的方法。任何建议或指导将不胜感激。

【问题讨论】:

标签: arrays typescript object lodash


【解决方案1】:

您不需要 lodash 或任何其他库,您可以使用 TS 来做到这一点。在返回之前循环遍历数组并分配给一个新对象。

grouped: { age: number, names: string[] }[] = [];

this.persons.forEach((person: Person) => {
  const groupIndex = this.grouped.findIndex((item: { age: number, names: string[] }) => {
    return item.age === person.age; });
    groupIndex !== -1 ? this.grouped[groupIndex].names.push(person.name)
    : this.grouped.push({age: person.age, names: [person.name]});
});

那么您的阵列可从this.grouped 获得。

我会为最终对象定义一个接口来整理它并使其更简洁:

export interface NamesByAge {
    age?: number;
    names?: string[];
}

所以最终的代码变成了:

grouped: NamesByAge[] = [];

this.persons.forEach((person: Person) => {
  const groupIndex = this.grouped.findIndex((item: NamesByAge) => {
    return item.age === person.age; });
    groupIndex !== -1 ? this.grouped[groupIndex].names.push(person.name)
    : this.grouped.push({age: person.age, names: [person.name]});
});

当然,这有点罗嗦,但您显然可以缩短变量名称,如果您更喜欢 if 而不是三元,但如果您不想为此包含一个库,它可以工作: ) 更好的是,作为一个函数:

sortByKey(array: any[], sort: string, collectionKey: string, collectionName: string) {
    const grouped: any[] = [];
    array.forEach((p: any) => {
      const gId = grouped.findIndex((i: any) => {
        return i[sort] === p[sort];
      });
      if (gId !== -1) {
        grouped[gId][collectionName].push(p[collectionKey]);
      } else {
        const obj: {} = {};
        obj[sort] = p[sort];
        obj[collectionName] = [p[collectionKey]];
        grouped.push(obj);
      }
    });
    return grouped;


sorted = this.sortByKey(this.persons, 'age', 'name', 'names');

【讨论】:

    【解决方案2】:

    此任务不需要 Lodash。 #NODASH :P

    这里是原生 JS 版本:

    const groupByAge = (objectMap, { age, name }) => {
      if (objectMap[age]) objectMap[age].push(name)
      else objectMap[age] = [name]
      return objectMap
    }
    
    const pairsToArray = (acc, [age, names]) => {
      acc.push({ age, names })
      return acc
    }
    
    const fn = sourceArray => {
      const groupedObject = sourceArray.reduce(groupByAge, {})
      return Object
        .entries(groupedObject)
        .reduce(pairsToArray, [])
    }
    

    这是带有类型声明的 TypeScript 版本(需要es2017.object):

    type GroupedObjectMap = { number: string[] }
    type SourcePerson = { age: number, name: string }
    type AgeGroup = { age: number, names: string[] }
    type AgeGroupTuple = [number, string[]]
    
    const groupByAge = (objectMap: {} | GroupedObjectMap, { age, name }: SourcePerson): {} | GroupedObjectMap => {
      if (objectMap[age]) objectMap[age].push(name)
      else objectMap[age] = [name]
      return objectMap
    }
    
    const pairsToArray = (acc: AgeGroup[], [age, names]: AgeGroupTuple): AgeGroup[] => {
      acc.push({ age, names })
      return acc
    }
    
    const fn = (sourceArray: SourcePerson[]): AgeGroup[] => {
      const groupedObject = sourceArray.reduce(groupByAge, {})
      return Object
        .entries(groupedObject)
        .reduce(pairsToArray, [])
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-05-31
      • 2019-02-25
      • 1970-01-01
      • 2020-05-02
      • 2020-09-16
      • 2021-02-23
      • 1970-01-01
      相关资源
      最近更新 更多