Javascript数组ab = ba

时间:2015-01-01 21:03:24

标签: javascript arrays for-loop multidimensional-array each

如果我有一个多维数组,例如:[[a,b],[a,c],[b,a],[b,c],[c,a],[c,b]]我如何通过并删除[a,b][b,a]相同的重复数据。

而且,阵列实际上是庞大的,成千上万。 for循环必须向后完成,因为数组长度会在每次迭代时缩小。我甚至不确定每个循环是否适用于此。我真的不知道如何开始的概念。

此外,我尝试搜索这个约一个小时,我甚至不知道如何用它来表达。

3 个答案:

答案 0 :(得分:1)

根据我的理解,你想要从父数组中删除任何包含相同对象集的子数组而不考虑顺序,这个应该这样做是一些代码:

function getId(obj) { // apparently these objects have identifiers
  return obj._id; // I'm testing with MongoDB documents
}
function arraysEqual(a, b) {
  if (a === b) { return true; }
  if (a == null || b == null) { return false; }
  if (a.length != b.length) { return false; }
  aIds = [];  bIds = [];
  for (var i = 0; i < a.length; i++) {
    aIds.push(getId(a[i])); bIds.push(getId(b[i]));
  }
  aIds.sort(); bIds.sort();
  for ( var i = 0; i < aIds.length; i++ ) {
    if(aIds[i] !== bIds[i]) { return false; }
  }
  return true;
}
function removeRepeats(list) {
  var i, j;
  for (i=0; i < list.length; i++) {
    for (j=i+1; j < list.length; j++) {
      if (arraysEqual(list[i], list[j])) {
        list.splice(j,1);
      }
    }
  }
}

removeRepeats函数遍历每个元素,并将其与之后的每个元素进行比较。 arraysEqual function simply returns true if the arrays are equalisEquivalent function。 {{3}}应该测试对象的等价性。如该网页所述,有些库可以测试对象的等价性。如果您可以添加这些库,则可以将isEquivalent函数替换为_.isEqual

答案 1 :(得分:1)

我想我会尝试不同的方法解决这个问题。我也认为它会比提出的一些解决方案更快(尽管我们当然需要对其进行测试并对其进行基准测试)。

首先,为什么我们不利用javascript数组和对象的散列导向性质?我们可以创建一个包含关系的对象(为了创建一种地图)并在新数组中存储那些尚未存储的关系。使用这种方法,对象也没有问题,我们只是为每个对象请求标识符或哈希或其他任何东西。该标识符必须使它们之间的关系成为可能。

<强>更新

  • 脚本现在控制重复元素f.e [[a,b],[a,b]]
  • 的可能性
  • 脚本现在控制重复相同对象的元素的可能性f.e [[a,a],[a,a] [a,a]]会返回[a,a]

代码:

var temp = {},
    massive_arr = [['a','b'],['a','c'],['a','d'], ['b','a'],['b','c'],['b','d'],['c','a'],['c','b'],['c','d']],
    final_arr = [],
    i = 0,
    id1,
    id2;
for( ; i < massive_arr.length; i++ ) {
    id0 = objectIdentifier(massive_arr[i][0]);// Identifier of first object
    id1 = objectIdentifier(massive_arr[i][1]);// Identifier of second object

    if(!temp[id0]) {// If the attribute doesn't exist in the temporary object, we create it.
        temp[id0] = {};
        temp[id0][id1] = 1;
    } else {// if it exists, we add the new key.
        temp[id0][id1] = 1;
    }

    if( id0 === id1 && !temp[id0][id1+"_bis"] ) {// Especial case [a,a]
        temp[id0][id1+"_bis"] = 1;
        final_arr.push(massive_arr[i]);
        continue;// Jump to next iteration
    }

    if (!temp[id1]) {// Store element and mark it as stored.
      temp[id1] = {};
      temp[id1][id0] = 1;
      final_arr.push(massive_arr[i]);
      continue;// Jump to next iteration
    }

    if (!temp[id1][id0]) {// Store element and mark it as stored.
      temp[id1][id0] = 1;
      final_arr.push(massive_arr[i]);
    }
}
console.log(final_arr);

function objectIdentifier(obj) {
    return obj;// You must return a valid identifier for the object. For instance, obj.id or obj.hashMap... whatever that identifies it unequivocally.
}

您可以对其进行测试here

第二次更新

虽然这不是首先要求的,但我已经改变了一些方法以使其适应n长度的元素(如果需要,n可以变化)。

由于依赖sort来为地图生成有效密钥,因此此方法较慢。即便如此,我认为它足够快。

var temp = {},
massive_arr = [
    ['a', 'a', 'a'], //0
    ['a', 'a', 'b'], //1
    ['a', 'b', 'a'],
    ['a', 'a', 'b'],
    ['a', 'c', 'b'], //2
    ['a', 'c', 'd'], //3
    ['b', 'b', 'c'], //4
    ['b', 'b', 'b'], //5
    ['b', 'b', 'b'],
    ['b', 'c', 'b'],
    ['b', 'c', 'd'], //6
    ['b', 'd', 'a'], //7
    ['c', 'd', 'b'],
    ['c', 'a', 'c'], //8
    ['c', 'c', 'a'],
    ['c', 'd', 'a', 'j'], // 9
    ['c', 'd', 'a', 'j', 'k'], // 10
    ['c', 'd', 'a', 'o'], //11
    ['c', 'd', 'a']
],
    final_arr = [],
    i = 0,
    j,
    ord,
    key;
for (; i < massive_arr.length; i++) {
    ord = [];
    for (j = 0; j < massive_arr[i].length; j++) {
        ord.push(objectIdentifier(massive_arr[i][j]));
    }

    ord.sort();
    key = ord.toString();

    if (!temp[key]) {
        temp[key] = 1;
        final_arr.push(massive_arr[i]);
    }
}

console.log(final_arr);

function objectIdentifier(obj) {
    return obj;
}

可以测试here

答案 2 :(得分:0)

*** 
* Turns out the OP has objects in his list, so this approach won't
* work in that case. I'll leave this for future reference.
***

var foo = [['a','b'],['a','c'],['b','a'],['b','c'],['c','a'],['c','b']];

function removeRepeats(list) {
    var i;
    var b = [];
    var _c = [];

    for (i = 0; i < list.length; i++) {
        var a = list[i].sort();
        var stra = a.join("-");

        if(_c.indexOf(stra) === -1) {
            b.push(a);
            _c.push(stra);
        }
    }

    return b;
}

console.log(removeRepeats(foo));

这不是我曾经制作的最漂亮的代码,但它应该足以让你开始我猜。我正在做的是创建两个新阵列b_cb将是没有重复的数组。 _c是一个帮助器数组,其中包含已经作为字符串处理的所有唯一对,因此我可以在循环list时进行简单的字符串比较。