在javascript中计算数组中的重复数组

时间:2014-07-16 10:18:50

标签: javascript arrays

我有一个数组数组如下:

    [[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中找到一个处理重复数组数组的例子。

4 个答案:

答案 0 :(得分:1)

假设子数组项的顺序很重要,假设您的子数组可以是可变长度并且可以包含除数字之外的项,那么这是解决问题的一种相当通用的方法。需要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]] 

on jsFiddle

答案 1 :(得分: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);

答案 2 :(得分:0)

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

修复了内部forEach循环变量名称以匹配大小写。还添加了一些var-keywords。

  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;
});

答案 3 :(得分:0)

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);