【问题标题】:How to count the number of the same items in an array and assign the count to a particular key in an object? [duplicate]如何计算数组中相同项目的数量并将计数分配给对象中的特定键? [复制]
【发布时间】:2020-06-30 03:51:11
【问题描述】:

我需要像下面这样转换一个数组:

["Cats", "Cats", "Dogs", "Dogs", "Dogs"]

以下形式:

[
    { x: "Cats", y: 35 },
    { x: "Dogs", y: 40 },
    { x: "Birds", y: 55 },
]

其中y表示数组中相同元素的个数。

【问题讨论】:

    标签: javascript arrays ecmascript-6


    【解决方案1】:

    另一种方法是使用Array#reduce() 有效地构建{ x : Animal, y : Count } 对象的字典,然后通过Object.values() 从字典中提取所需的值数组:

    const input = ["Cats", "Cats", "Dogs", "Dogs", "Dogs"]
    
    /* Obtain array of values from reduced dictionary */
    const result = Object.values(input.reduce((dict, value) => {
      
      /* Fetch, or insert starting item for value in dictionary */
      const item = dict[value] || { x : value, y : 0 }
      
      /* Increment y counter for item */
      item.y++;
    
      /* Update dictionary value with item */  
      dict[value] = item;
    
      return dict
    
    }, {}));
    
    console.log(result);

    这种方法的一个优点是它避免了overhead of an extra call to .map(),使其更有效。

    【讨论】:

    • 或const result = Object.entries(input.reduce((a, v) => (a[v]=(a[v]||0)+1, a), {})) .map(([x, y]) => ({x, y}));
    • @JaromandaX 是的,可以。如果可能的话,最好避免额外的map() :)
    • @JaromandaX Lol 几乎完全相同的答案,甚至没有注意到
    • 如果担心效率,应该避免每次迭代复制对象 O(n^2) 时间。
    • @Ry-point 已被采纳,已更新答案
    【解决方案2】:

    这是使用对象查找的更快版本:

    const arr = ["Cats", "Cats", "Dogs", "Dogs", "Dogs", "Birds"];
    const result = Object.entries(arr.reduce((acc, cur) => {
      acc[cur] = (acc[cur] || 0) + 1;
      return acc;
    }, Object.create(null))).map(([x, y]) => ({x, y}));
    
    console.log(result);

    编辑

    正如 Ry-♦ 所提到的,存在一个潜在的错误,即字符串 "__proto__" 等无法正确计数。所以从{}改为Object.create(null)以避免它。

    【讨论】:

    • 这可能与Object.prototype 属性发生冲突。如果支持,最好使用Map(它也允许字符串以外的类型),或者在紧要关头使用Object.create(null)。
    【解决方案3】:

    强调使用高效、现代的基于Map 的方法,该方法也可以在副本中以类似的形式找到:

    const getCounts = iterable => {
        const counts = new Map();
    
        for (const x of iterable) {
            counts.set(x, (counts.get(x) ?? 0) + 1);  // use || for ES6 compat
        }
    
        return counts;
    };
    
    Array.from(
        getCounts(["Cats", "Cats", "Dogs", "Dogs", "Dogs"]),
        ([x, y]) => ({x, y})
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-13
      • 2021-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-22
      • 1970-01-01
      相关资源
      最近更新 更多