【问题标题】:Grouping Data in TypeScript Array在 TypeScript 数组中分组数据
【发布时间】:2021-12-29 21:43:01
【问题描述】:

我的 JSON 数据如下所示:

[
    {
        "id": 1,
        "tags": [
            "Test 1",
            "Test 2",
            "Test 3"
        ]
    },
    {
        "id": 2,
        "tags": [
            "Test 2",
            "Test 3",
            "Test 4"
        ]
    },
    {
        "id": 3,
        "tags": [
            "Test 3",
            "Test 4"
        ]
    }
]

我想将其转换为如下所示的数据:

[
    {
        "name": "Test 1",
        "count": 1
    },
    {
        "name": "Test 2",
        "count": 2
    },
    {
        "name": "Test 3",
        "count": 3
    },
    {
        "name": "Test 4",
        "count": 1
    }
]

我可以想出一些粗暴的方法来做到这一点,但我希望有一些更高效、更性感的东西?可能使用.groupBy().reduce()

感谢您抽出宝贵时间查看我的问题。

【问题讨论】:

  • 遍历数据结构并没有什么特别的魅力。你有什么解决方案,你觉得太暴力了?

标签: arrays typescript grouping


【解决方案1】:

我愿意:

interface Item {
  id: number,
  tags: string[]
}

function countOccurences(a: string[]) {
  return a.reduce(function (acc: {[key: string]: number}, curr: string) {
    acc[curr] ??= 0;
    acc[curr]++;
    return acc;
  }, {});
}

const data: Item[] = JSON.parse(json);
const tagOccurences = countOccurences(data.flatMap(o => o.tags))

Playground link

【讨论】:

    【解决方案2】:

    您可以在reduce 中使用reduce 对标签进行分组。

    const array = [{
        id: 1,
        tags: ['Test 1', 'Test 2', 'Test 3'],
      },
      {
        id: 2,
        tags: ['Test 2', 'Test 3', 'Test 4'],
      },
      {
        id: 3,
        tags: ['Test 3', 'Test 4'],
      },
    ];
    
    const frequencies = Object.values(array.reduce((acc, curr) =>
      curr.tags.reduce(
        (nAcc, tag) => ((nAcc[tag] ??= {name: tag,count: 0}),nAcc[tag].count++,nAcc),
        acc
      ), {}
    ));
    console.log(frequencies);

    在 TypeScript 中:

    const array = [{
        id: 1,
        tags: ['Test 1', 'Test 2', 'Test 3'],
      },
      {
        id: 2,
        tags: ['Test 2', 'Test 3', 'Test 4'],
      },
      {
        id: 3,
        tags: ['Test 3', 'Test 4'],
      },
    ];
    
    type Frequency = {
        name: string,
        count: number
    }
    
    const frequencies = Object.values(array.reduce((acc, curr) =>
      curr.tags.reduce(
        (nAcc, tag) => ((nAcc[tag] ??= {name: tag,count: 0}),nAcc[tag].count++,nAcc),
        acc
      ), {} as Record<string, Frequency>
    ));
    console.log(frequencies); 
    

    Playground

    【讨论】:

      【解决方案3】:

      使用for...of 迭代和Map 作为缓存是一种非常直接的方法......而且很性感。

      TS Playground

      type TagsWithId = {
        id: number;
        tags: string[];
      };
      
      type TagCount = {
        count: number;
        name: string;
      };
      
      function verySexyTagCounter (input: TagsWithId[]): TagCount[] {
        const map = new Map<string, number>();
      
        for (const {tags} of input) {
          for (const name of tags) {
            map.set(name, (map.get(name) ?? 0) + 1);
          }
        }
      
        return [...map.entries()].map(([name, count]) => ({name, count}));
      }
      
      const json = `[{"id":1,"tags":["Test 1","Test 2","Test 3"]},{"id":2,"tags":["Test 2","Test 3","Test 4"]},{"id":3,"tags":["Test 3","Test 4"]}]`;
      const input: TagsWithId[] = JSON.parse(json);
      
      const result = verySexyTagCounter(input);
      console.log(result);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-11-25
        • 2021-05-29
        • 1970-01-01
        • 1970-01-01
        • 2022-12-14
        • 1970-01-01
        • 2017-09-10
        • 2021-04-13
        相关资源
        最近更新 更多