在JavaScript中创建数组中重复项的映射

Creating a mapping of duplicates in array in JavaScript

本文关键字:映射 数组 JavaScript 创建      更新时间:2023-09-26

我正在尝试创建一个函数,该函数创建一个对象,并计算数组中每个数字的重复次数。例如,如果我有一个[1,2,2,2,3,3]的数组,我的函数应该返回3,因为2有两个副本,3有一个副本。所以我写了一个我认为很聪明的函数。我决定创建每个元素的频率映射。通过设置每个新属性的创建,即数组中的唯一数字等于-1。出于某种原因,当我这样做时,我得到的属性值都等于零。我从下面的两个函数中得到了两组不同的结果。

function DistinctListV1(arr) { 
  var mapping = {};
      for(var i = 0; i < arr.length; i++){
        if(!mapping[arr[i]]){
          mapping[arr[i]] = 0; //Difference here
        }
          mapping[arr[i]] += 1;
      }         
return mapping
}

function DistinctListV2(arr) { 
  var mapping = {};
      for(var i = 0; i < arr.length; i++){
        if(!mapping[arr[i]]){
          mapping[arr[i]] = -1; //Difference here
        }
          mapping[arr[i]] += 1;
      }         
return mapping
}

DistinctListV1([1,2,2,3,3,3]) 
=> { '1': 1, '2': 2, '3': 3 }
DistinctListV2([1,2,2,3,3,3])   
=> { '1': 0, '2': 0, '3': 0 }  

现在我只关心用这个映射创建一个对象。感谢阅读。

编辑:

=> DistinctListV3([1,2,2,3,3,3])
function DistinctListV3(arr) { 
  var mapping = {};
      for(var i = 0; i < arr.length; i++){
        if(!mapping[arr[i]]){
          mapping[arr[i]] = 100; //Difference here
        }
          mapping[arr[i]] += 1;
      }         
return mapping
}
DistinctListV3([1,2,2,3,3,3])
=> { '1': 101, '2': 102, '3': 103 }

使用这个例子,让我相信当我使用-1作为开始递增的地方时,发生了一些事情。

您遇到的问题是由以下行引起的:

if(!mapping[arr[i]]){

我认为您希望if中的代码只在mapping[arr[i]]还不存在时运行。但!运算符并不严格:不仅当mapping[arr[i]]undefined时,它还会返回true,而且当mapping[arr[i]]任何错误的东西时,例如数字零。当然,当您将变量初始化为-1,然后将1添加到其中时,就会发生这种情况,导致所有映射都无限期地停留在0(它们一直设置为-1,然后递增,这意味着它们回到0if一次又一次地运行,永远不会超过0)。

你想要更严格的检查:

if (typeof mapping[arr[i]] === 'undefined') {

if (mapping.hasOwnProperty(arr[i])) {

如果您只是动态创建对象呢?

类似于:

var counterObject = {};
var duplicateCounter = 0;
for (var i = 0; i < array.length; i ++ ){
    var item = array[i];
    if (!counterObject[item]) {
       counterObject[item] = 'placeholder';
    } else {
       duplicateCounter++
    }
}

我没有测试它,但流程是:循环遍历数组,在i处获取项。根据对象检查i处的项。如果它在那里,那么它一定是重复的,所以我们增加重复计数器。如果没有,我们会指定一些以项目名称为键的任意值,这样当我们再次遇到它时,我们可以递增。如果还想查看每个值的数量,可以将"占位符"设置为0,然后在else{}中递增对象中该值的计数。

!mapping[arr[i]]undefined0true,这就是为什么第一个有效,而第二个无效。第一次将1添加到DistinctListV2mapping上的属性时,它变为0,然后下一次找到相同的数字时,!mapping[arr[i]]就是true,因此它再次将该属性设置为-1。

修复方法很简单:

function DistinctListV2(arr) { 
  var mapping = {};
      for(var i = 0; i < arr.length; i++){
        if(mapping[arr[i]] === undefined){ // Check for undefined, not 'falsey'
          mapping[arr[i]] = -1;
        }
          mapping[arr[i]] += 1;
      }         
return mapping
}