【问题标题】:counting duplicate arrays within an array in javascript在javascript中计算数组中的重复数组
【发布时间】:2021-06-13 13:48:56
【问题描述】:

我有一个数组如下:

    [[3, 4], [1, 2], [3, 4]]

我希望创建一个没有重复的数组的新数组,并且计算第一个数组中每个元素的出现次数:

    [[3,4,2], [1,2,1]]

这是我目前所拥有的:

var alreadyAdded = 0; 
dataset.forEach(function(data) {
 From = data[0];
 To = data[1];

 index = 0;
 newDataSet.forEach(function(newdata) {
  newFrom = newData[0];
  newTo = newData[1];

  // check if the point we are looking for is already added to the new array
  if ((From == newFrom) && (To == newTo)) {

   // if it is, increment the count for that pair
   var count = newData[2];
   var newCount = count + 1;
   newDataSet[index] = [newFrom, newTo, newCount];
   test = "reached here";
   alreadyAdded = 1;
  }
  index++;
 });

 // the pair was not already added to the new dataset, add it
 if (alreadyAdded == 0) {
  newDataSet.push([From, To, 1]);
 }

 // reset alreadyAdded variable
 alreadyAdded = 0;
});

我对 Javascript 很陌生,有人可以帮我解释一下我做错了什么吗?我确信有一种更简洁的方法可以做到这一点,但是我无法在 javascript 中找到处理重复数组数组的示例。

【问题讨论】:

  • [3, 4][4, 3] 会被视为相同还是顺序很重要?
  • 您能澄清一下您期望的结果吗?我不明白你是怎么得到[[3,4,2], [1,2,1]]
  • [3,4] 似乎与[4,3] 不同。如果您正在查看 OP 代码中使用的变量,它看起来每个数组只包含两个元素,第一个是某物在事件之前的位置,最后一个是它在事件之后的位置。因此,从3 移动到4 与从4 移动到3 不同。

标签: javascript arrays


【解决方案1】:

根据您要迭代的数据集有多大,我会谨慎地对它进行多次循环。您可以通过为原始数据集中的每个元素创建一个“索引”然后使用它来引用分组中的元素来避免这样做。这是我解决问题时采用的方法。你可以在 jsfiddle 上看到它here。我使用Array.prototype.reduce 创建了一个对象文字,其中包含来自原始数据集的元素分组。然后我迭代了它的键来创建最终的分组。

var dataSet = [[3,4], [1,2], [3,4]],
    grouping = [],
    counts,
    keys,
    current;

counts = dataSet.reduce(function(acc, elem) {
    var key = elem[0] + ':' + elem[1];
    if (!acc.hasOwnProperty(key)) {
        acc[key] = {elem: elem, count: 0}
    }
    acc[key].count += 1;
    return acc;
}, {});

keys = Object.keys(counts);
for (var i = 0, l = keys.length; i < l; i++) {
    current = counts[keys[i]];
    current.elem.push(current.count);
    grouping.push(current.elem);
}

console.log(grouping);

【讨论】:

  • 谢谢科林!您的解决方案更优雅,运行速度更快,因为数据集确实很大。 reduce 函数似乎非常有用,我可能会一遍又一遍地使用它:)
【解决方案2】:

假设子数组项的顺序很重要,假设您的子数组可以是可变长度的并且可以包含除数字以外的项,这是解决问题的一种相当通用的方法。需要目前的 ECMA5 兼容性,但在 ECMA3 上运行并不难。

Javascript

// Create shortcuts for prototype methods
var toClass = Object.prototype.toString.call.bind(Object.prototype.toString),
    aSlice = Array.prototype.slice.call.bind(Array.prototype.slice);

// A generic deepEqual defined by commonjs
// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
function deepEqual(a, b) {
    if (a === b) {
        return true;
    }

    if (toClass(a) === '[object Date]' && toClass(b) === '[object Date]') {
        return a.getTime() === b.getTime();
    }

    if (toClass(a) === '[object RegExp]' && toClass(b) === '[object RegExp]') {
        return a.toString() === b.toString();
    }

    if (a && typeof a !== 'object' && b && typeof b !== 'object') {
        return a == b;
    }

    if (a.prototype !== b.prototype) {
        return false;
    }

    if (toClass(a) === '[object Arguments]') {
        if (toClass(b) !== '[object Arguments]') {
            return false;
        }

        return deepEqual(aSlice(a), aSlice(b));
    }

    var ka,
        kb,
        length,
        index,
        it;

    try {
        ka = Object.keys(a);
        kb = Object.keys(b);
    } catch (eDE) {
        return false;
    }

    length = ka.length;
    if (length !== kb.length) {
        if (Array.isArray(a) && Array.isArray(b)) {
            if (a.length !== b.length) {
                return false;
            }
        } else {
            return false;
        }
    } else {
        ka.sort();
        kb.sort();
        for (index = 0; index < length; index += 1) {
            if (ka[index] !== kb[index]) {
                return false;
            }
        }
    }

    for (index = 0; index < length; index += 1) {
        it = ka[index];
        if (!deepEqual(a[it], b[it])) {
            return false;
        }
    }

    return true;
};

// Recursive function for counting arrays as specified
// a must be an array of arrays
// dupsArray is used to keep count when recursing
function countDups(a, dupsArray) {
    dupsArray = Array.isArray(dupsArray) ? dupsArray : [];

    var copy,
        current,
        count;

    if (a.length) {
        copy = a.slice();
        current = copy.pop();
        count = 1;
        copy = copy.filter(function (item) {
            var isEqual = deepEqual(current, item);

            if (isEqual) {
                count += 1;
            }

            return !isEqual;
        });

        current.push(count);
        dupsArray.push(current);
        if (copy.length) {
            countDups(copy, dupsArray);
        }
    }

    return dupsArray;
}

var x = [
    [3, 4],
    [1, 2],
    [3, 4]
];

console.log(JSON.stringify(countDups(x)));

输出

[[3,4,2],[1,2,1]] 

jsFiddle

【讨论】:

    【解决方案3】:

    修复错字后,我在调试器中尝试了您的解决方案;它有效!

    修复了内部 forEach-loop 变量名称以匹配大小写。还添加了一些 var 关键字。

      var alreadyAdded = 0;
      dataset.forEach(function (data) {
        var From = data[0];
        var To = data[1];
    
        var index = 0;
        newDataSet.forEach(function (newData) {
            var newFrom = newData[0];
            var newTo = newData[1];
    
            // check if the point we are looking for is already added to the new array
            if ((From == newFrom) && (To == newTo)) {
    
                // if it is, increment the count for that pair
                var count = newData[2];
                var newCount = count + 1;
                newDataSet[index] = [newFrom, newTo, newCount];
                test = "reached here";
                alreadyAdded = 1;
            }
            index++;
        });
    
        // the pair was not already added to the new dataset, add it
        if (alreadyAdded == 0) {
            newDataSet.push([From, To, 1]);
        }
    
        // reset alreadyAdded variable
        alreadyAdded = 0;
    });
    

    【讨论】:

    • 谢谢超级!没有意识到这是一个小小的错字!
    【解决方案4】:

    const x = [[3, 4], [1, 2], [3, 4]];
    
    const with_duplicate_count = [
      ...x
        .map(JSON.stringify)
        .reduce( (acc, v) => acc.set(v, (acc.get(v) || 0) + 1), new Map() )
        .entries()
    ].map(([k, v]) => JSON.parse(k).concat(v));
    
    console.log(with_duplicate_count);

    【讨论】:

      猜你喜欢
      • 2021-08-29
      • 1970-01-01
      • 2013-10-24
      • 1970-01-01
      • 2013-04-20
      • 1970-01-01
      • 1970-01-01
      • 2014-02-24
      • 2012-11-01
      相关资源
      最近更新 更多