将TypeScript对象数组中的数据分组到不同的对象数组

时间:2018-06-15 20:38:03

标签: arrays typescript object lodash

在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',它映射到一个字符串和一个键{{ 1}}映射到字符串数组。

所以最终得到的数组如下所示:

'names'

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

2 个答案:

答案 0 :(得分:0)

您不需要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');

答案 1 :(得分:0)

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

这是vanilla 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, [])
}