【问题标题】:How do I count the number of occurrences of a value in an array without mutation如何计算没有突变的数组中值的出现次数
【发布时间】:2019-01-27 01:18:15
【问题描述】:

我目前有一个数组数组,其中包含所有具有相同序列号的部件。我想要做的是只过滤掉具有相同序列号和相同部件号的部件。我目前能够获得所有唯一零件编号的列表,但我一生都无法弄清楚如何仅取出具有相同零件编号和相同序列号的物品。数组是按序号排序的,所以

dupes = [
[{ sn: 001, partNum: 2505}]
[{ sn: 001, partNum: 9999}]
[{ sn: 001, partNum: 9999}],
[{ sn: 002, partNum: 1234}]
[{ sn: 002, partNum: 1234}],
[{ sn: 003, partNum: 555}]
[{ sn: 003, partNum: 8675}]]

我想要得到的是一个只包含重复项的数组

[{ sn: 001, partNum: 9999}]
[{ sn: 001, partNum: 9999}],
[{ sn: 002, partNum: 1234}]
[{ sn: 002, partNum: 1234}]

我整天都在努力解决这个问题,但没有找到不使用突变的好解决方案。如果零件号出现两次,有没有办法过滤掉“SN”?我还必须检查每个零件号,因为在少数情况下,我看到两个不同的零件号每次使用相同的序列号两次,如果这样的话。 任何帮助都会很棒......严重卡在这里。

编辑:

我最终以不同的方式完成了这项任务。不过,我确实找到了一个很好的函数,可以让您计算数组中某个项目的所有出现次数。

function count(arr) {
  return arr.reduce((prev, curr) => (prev[curr] = ++prev[curr] || 1, prev), {})
}

我在这里找到它https://code.i-harness.com/en/q/567c30

【问题讨论】:

  • 你能举例说明你的预期输出吗?
  • 所以结果应该是 [{ sn: 001, partNum: 9999}] 和 [{ sn: 002, partNum: 1234}] ?
  • @JohnEllmore 我更新了我的代码以显示我想要实现的理想目标。
  • 你在寻找一个普通的 JS 解决方案吗?还是您愿意使用 Lodash 之类的库?
  • @JohnEllmore 我试图让一切都保持原样。

标签: javascript arrays sorting functional-programming


【解决方案1】:

如果你想要所有的重复:

var dupes = [
[{ sn: 001, partNum: 2505}],
[{ sn: 001, partNum: 9999}],
[{ sn: 001, partNum: 9999}],
[{ sn: 002, partNum: 1234}],
[{ sn: 002, partNum: 1234}],
[{ sn: 003, partNum: 555}],
[{ sn: 003, partNum: 8675}]]

var result = [];
for(i =1; i<dupes.length; i++) {
  if(dupes[i-1][0].sn == dupes[i][0].sn ) {
    if(dupes[i-1][0].partNum == dupes[i][0].partNum ) {
      result.push(dupes[i-1]);
      result.push(dupes[i]);
    }
  }
}
console.log(result);

无突变:您可以在函数内部声明结果数组,并且由于您没有更改欺骗,因此该函数将是纯的。

var dupes = [
[{ sn: 001, partNum: 2505}],
[{ sn: 001, partNum: 9999}],
[{ sn: 001, partNum: 9999}],
[{ sn: 002, partNum: 1234}],
[{ sn: 002, partNum: 1234}],
[{ sn: 003, partNum: 555}],
[{ sn: 003, partNum: 8675}]]


function onlyDuplicates(dupes) {
  var result = [];
  for(i =1; i<dupes.length; i++) {
    if(dupes[i-1][0].sn == dupes[i][0].sn ) {
      if(dupes[i-1][0].partNum == dupes[i][0].partNum ) {
        result.push(dupes[i-1]);
        result.push(dupes[i]);
      }
    }
  }
  return result;
}

console.log(onlyDuplicates(dupes));

【讨论】:

  • 我曾想过做类似的事情,但“推送”不是数组的突变吗?我知道数组result 是一个空数组,将在函数内限定范围,但这是否会使函数本身由于突变而“不纯”?还是只要没有超出函数范围的突变,函数仍然是纯函数?
  • @JustinGagnon 我也添加了一个没有突变的解决方案
  • @JohnEllmore 这就是你想要的吗?
  • 您的解决方案是错误的。有关详细信息,请参阅我的answer
【解决方案2】:

McRist 的解决方案有很多问题。例如,如果它们不相邻,它不会找到重复项:

var dupes = [ [ { sn: 001, partNum: 2505 } ]
            , [ { sn: 001, partNum: 9999 } ] // element 1
            , [ { sn: 002, partNum: 1234 } ] // element 2
            , [ { sn: 001, partNum: 9999 } ] // duplicate of element 1
            , [ { sn: 002, partNum: 1234 } ] // duplicate of element 2
            , [ { sn: 003, partNum: 555  } ]
            , [ { sn: 003, partNum: 8675 } ]
            ];

var result = [];

for (var i = 0, j = 1; j < dupes.length; i++, j++) {
    if (dupes[i][0].sn      === dupes[j][0].sn &&
        dupes[i][0].partNum === dupes[j][0].partNum) {
        result.push(dupes[i]);
        result.push(dupes[j]);
    }
}

// empty array, even though there are duplicates
console.log(JSON.stringify(result));

更糟糕的是,如果有两个以上的连续重复,那么它会返回额外的元素:

var dupes = [ [ { sn: 001, partNum: 2505 } ]
            , [ { sn: 001, partNum: 9999 } ] // element 1
            , [ { sn: 001, partNum: 9999 } ] // duplicate of element 1
            , [ { sn: 001, partNum: 9999 } ] // duplicate of element 1
            , [ { sn: 003, partNum: 555  } ]
            , [ { sn: 003, partNum: 8675 } ]
            ];

var result = [];

for (var i = 0, j = 1; j < dupes.length; i++, j++) {
    if (dupes[i][0].sn      === dupes[j][0].sn &&
        dupes[i][0].partNum === dupes[j][0].partNum) {
        result.push(dupes[i]);
        result.push(dupes[j]);
    }
}

// four elements, even though there are only three duplicates
console.log(JSON.stringify(result));

这是一个仅正确返回重复元素的解决方案。此外,它不使用任何类型的突变:

var dupes = [ [ { sn: 001, partNum: 2505 } ]
            , [ { sn: 001, partNum: 9999 } ] // element 1
            , [ { sn: 002, partNum: 1234 } ] // element 2
            , [ { sn: 002, partNum: 1234 } ] // duplicate of element 2
            , [ { sn: 002, partNum: 1234 } ] // duplicate of element 2
            , [ { sn: 001, partNum: 9999 } ] // duplicate of element 1
            , [ { sn: 003, partNum: 555  } ]
            , [ { sn: 003, partNum: 8675 } ]
            ];

const duplicates = (xs, eq) =>
    xs.filter((x, i) =>      // filter those elements
        xs.some((y, j) =>    // for which there's another element
            i !== j &&       // which is not the same and
            eq(x, y)));      // is a duplicate

const eq = ([x], [y]) =>     // two elements are the same if
    x.sn      === y.sn &&    // they have the same serial number and
    x.partNum === y.partNum; // the same part number

// correctly returns all five duplicates
console.log(JSON.stringify(duplicates(dupes, eq)));

希望对您有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-15
    • 1970-01-01
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    • 2015-06-18
    • 1970-01-01
    相关资源
    最近更新 更多