【问题标题】:Get frequencies of objects in an array using reduce and map使用reduce和map获取数组中对象的频率
【发布时间】:2017-02-17 18:52:31
【问题描述】:

我正在尝试编写一个函数,该函数将接收一个数组,然后返回数组中每个对象的频率映射。例如,对于以下数组:

freqs([1, 2, 3, 7, 2, 7, 1, 2, 1]) 

它将返回如下地图:

Map {1 => 3, 2 => 3, 3 => 1, 7 => 2}

这是我目前所拥有的:

function freqs(items) {
    return items.reduce(function(prev, curr)
    {
        if (curr in prev)
        {
            prev[curr]++;
        }
        else
        {
            prev[curr]=1;
        }

        return prev.map();
    });

}

但是,当我尝试对其进行测试时,我收到以下错误:

未捕获的 TypeError:无法使用 'in' 运算符在 1 中搜索 '1'

这是什么原因造成的?另外,我的逻辑正确吗?我觉得我做错了什么。

【问题讨论】:

    标签: javascript arrays dictionary reduce


    【解决方案1】:

    您可以使用Array.prototype.reduce() 将对象的属性设置为数组元素的值,为每个匹配的元素递增值; Object.keys(), Array.prototype.forEach() 设置Map的值

    var freq = (arr) =>  {
      var map = new Map();
      var obj = {};
      Object.keys(arr.reduce((obj, prop) => {
          return (prop in obj ? ++obj[prop] : (obj[prop] = 1)), obj
        }, obj)).forEach(el => map.set(el, obj[el]));
      return map
    };
    
    var arr = [1, 2, 3, 7, 2, 7, 1, 2, 1];
    
    console.log(freq(arr));

    【讨论】:

      【解决方案2】:
      1. 如果您没有为reduce 提供初始值,默认情况下它将使用第一个元素作为初始值。在您的情况下,prev 变为 1。这就是您收到此错误的原因。您应该将初始值设置为 Map 对象。

      2. prev.map() - 我不知道意图是什么

      3. 当您执行prev[curr] 时,您将prev 用作普通的JavaScript 对象。 Maps 没有括号符号来访问它们的值。


      你的固定程序应该是这样的

      function freqs(items) {
        return items.reduce(function(prev, c) {
          if (prev.has(c)) {  // use `has` and `set` operations on Map objects
            prev.set(c, prev.get(c) + 1);
          } else {
            prev.set(c, 1);
          }
          return prev;    // return the map, so it will be prev for the next iteration
        }, new Map());    // Set the initial value to a new Map object
      }
      
      console.log(freqs([1, 2, 3, 7, 2, 7, 1, 2, 1]));
      // Map { 1 => 3, 2 => 3, 3 => 1, 7 => 2 }
      

      【讨论】:

      • 或者干脆return prev.set(c, (prev.get(c) || 0) + 1)
      【解决方案3】:

      您在使用 ccurrpprev 时不一致。 您以错误的方式使用map
      相反,只需return prev;
      接下来,您需要为prev-变量设置一个初始值。这应该是一个空对象{},作为reduce 的第二个参数。这样做,你应该没问题。

      function freqs(items) {
          return items.reduce(function(prev, curr)
          {
              if (curr in prev)
              {
                  prev[curr]++;
              }
              else
              {
                  prev[curr]=1;
              }
      
              return prev;
          },{});
      
      }
      

      【讨论】:

      • 我修复了变量差异。是的,您的版本有效。你能解释一下我做错了什么吗?
      • @FlameDra 当然!我发布了一个链接,指向map() 函数的解释。它将一个函数作为属性并将其应用于数组/obj 的每个元素,最后返回一个新值的数组。你在这里不需要这个。只需返回对象 prev 本身。在function(prev, curr) {...} 之后,我添加了{} 作为第二个参数。这是 prev 的初始值,因为您首先需要一个对象,然后才能创建prev[curr]。希望这可以帮助。询问,如果没有。
      • @FlameDra 但是改用“thefourtheye”的解决方案。最好真正使用地图。我只使用对象。
      猜你喜欢
      • 2021-12-02
      • 2019-02-27
      • 2021-01-25
      • 2020-08-23
      • 2018-12-07
      • 2023-02-26
      • 2023-03-10
      • 2021-10-30
      • 2016-03-12
      相关资源
      最近更新 更多