【问题标题】:forEach method seems to skip an entryforEach 方法似乎跳过了一个条目
【发布时间】:2021-06-08 01:32:19
【问题描述】:

目标

我正在尝试创建一个函数,该函数将采用“投票”数组并返回一个对象,该对象包含每个“候选人”获得 1 分的次数。

例如一个数组,如:

[
    {
        "blue": 1,
        "red": 3,
        "purple": 2,
        "yellow": 4
    },
    {
        "blue": 2,
        "red": 3,
        "purple": 4,
        "yellow": 1
    },
    {
        "blue": 1,
        "red": 2,
        "purple": 4,
        "yellow": 3
    },
    {
        "blue": 3,
        "red": 4,
        "purple": 2,
        "yellow": 1
    }
];

应该返回一个对象

{
    "blue": 2,
    "red": 0,
    "purple": 0,
    "yellow": 2
}

当前代码

目前我已经写好了函数

// adds up the first choice results from raw data
// return object containing number of first choice votes each candidate received
const add_first_choices = function (raw_data) {
    // create object to store number of first choices
    const storage_obj = empty_candidate_obj(raw_data);

    // loop through results, adding first choices to storage_obj
    raw_data.forEach(function (single_voter_obj) {
        Object.values(single_voter_obj).forEach(function (value) {
            if (value === 1) {
                storage_obj[getKeyByValue(single_voter_obj, value)] += 1;
            }
        });
    });
    return storage_obj;
};

它使用以下两个其他函数

// returns object of candidate names, each with value of 0
const empty_candidate_obj = function (raw_data) {
    const input_data = raw_data;
    let first_vote = input_data[0];
    const keys = Object.keys(first_vote);
    keys.forEach(function (key) {
        first_vote[key] = 0;
    });
    return first_vote;
};

// returns key from object value
const getKeyByValue = function (object, value) {
    return Object.keys(object).find((key) => object[key] === value);
};

问题

当将上面的数组输入到我的函数中时,它会返回

{
    blue: 1,
    red: 0,
    purple: 0,
    yellow: 2
}

=> 不如预期!

你知道我做错了什么吗?

感谢任何回复:)

【问题讨论】:

  • const output = {}; for (const o of raw_data) { for (const key in o) { output[key] ||= 0; if (o[key] === 1) output[key]++ } }
  • 在这种情况下,调试技巧就派上用场了。查看this article 了解一些提示,开始吧。

标签: javascript node.js arrays object


【解决方案1】:

问题在于这一行:

const input_data = raw_data;

复制对象数组是有问题的,因为复制数组不会自动生成对象的新副本。它只是一个引用原始对象的新数组,因此如果您更改新数组中的一个对象,您就是在更改原始对象。

所以你也需要new copies of the objects

const input_data = raw_data.map(obj => ({...obj}));

您可以使用reduce 稍微简单地解决您的问题。

const data = [{"blue":1,"red":3,"purple":2,"yellow":4},{"blue":2,"red":3,"purple":4,"yellow":1},{"blue":1,"red":2,"purple":4,"yellow":3},{"blue":3,"red":4,"purple":2,"yellow":1}];

// We initialise the `reduce` with a new `{}` object,
// which is updated with each iteration.
// `acc` is the accumulator, `c` is the current element
const result = data.reduce((acc, c) => {

  // For each object in the array we grab the key and value
  Object.entries(c).forEach(([ key, value ]) => {

    // If our initial object doesn't already have a key
    // that matches, create one and set it to zero
    acc[key] = acc[key] || 0;

    // And if the value is one, increase the value of that property
    if (value === 1) acc[key]++;
  });

  // Make sure to return the initial object
  // for the next iteration
  return acc;
}, {});

console.log(result);

【讨论】:

    【解决方案2】:

    关于您的代码,问题出在这行 empty_candidate_obj 函数

      let first_vote = input_data[0];
    

    更新您的代码以发送副本

    let first_vote = {...input_data[0]};

    对象在参考上起作用。所以就像您的数据集值的第一个对象也与您的空对象一起更新为 0

    【讨论】:

      【解决方案3】:

      你可能想使用这样的 reducer:

      const results = [
          {
              "blue": 1,
              "red": 3,
              "purple": 2,
              "yellow": 4
          },
          {
              "blue": 2,
              "red": 3,
              "purple": 4,
              "yellow": 1
          },
          {
              "blue": 1,
              "red": 2,
              "purple": 4,
              "yellow": 3
          },
          {
              "blue": 3,
              "red": 4,
              "purple": 2,
              "yellow": 1
          }
      ];
      
      const empty_obj = {
          "blue": 0,
          "red": 0,
          "purple": 0,
          "yellow": 0
      }
      result = results.reduce( reducer , empty_obj)
      console.log( result )
      
      function reducer( acc, val ) {
        for( key in val )
          if( val[key] === 1 ) acc[key]++;
      
        return acc;
      }

      【讨论】:

        【解决方案4】:

        试试这个功能:

        function candidateScore1Times(array) {
          const newObj = {}
        
          for (const score of array) {
            Object.keys(score).forEach(elem => {
              if (newObj[elem] != null)  {
                if (score[elem] == 1) {
                  newObj[elem]++
                }
              } else {
                score[elem] == 1 ? newObj[elem] = 1 : newObj[elem] = 0
              }
            })
          }
          return newObj
        }

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-03-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多