如何有效地检查数组是否包含特定数组

时间:2018-05-30 13:02:52

标签: javascript

我需要排序和删除顶点,我使用了这个东西。但最近我意识到这种方法很慢。

function Face(v1, v2, v3) {
  var df = Math.hypot(v2[0] * 1 - v3[0] * 1, v2[1] * 1 - v3[1] * 1, v2[2] * 1 - v3[2] * 1);
  if (df != 0) {
    for (var dp = 0; dp < df; dp += gap) {
      x = v3[0] * 1 + (v2[0] * 1 - v3[0] * 1) / df * dp;
      y = v3[1] * 1 + (v2[1] * 1 - v3[1] * 1) / df * dp;
      z = v3[2] * 1 + (v2[2] * 1 - v3[2] * 1) / df * dp;
      var ds = Math.hypot(x - v1[0] * 1, y - v1[1] * 1, z - v1[2] * 1);
      if (ds != 0) {
        for (var dps = 0; dps < ds; dps += gap) {
          fx = v1[0] * 1 + (x - v1[0] * 1) / ds * dps;
          fy = v1[1] * 1 + (y - v1[1] * 1) / ds * dps;
          fz = v1[2] * 1 + (z - v1[2] * 1) / ds * dps;
          var ffx = Math.round(fx / gap) * gap;
          var ffy = Math.round(fy / gap) * gap;
          var ffz = Math.round(fz / gap) * gap;

          if (check) {
            if (!(findOne(output, [ffx, ffy, ffz]))) {
              output.push([ffx, ffy, ffz]);
            }
          } else {
            output.push([ffx, ffy, ffz]);
          }
        }
      }
    }
  }
}

脸部(vertex1,vertex2,vertex3); 没有检查,更快。 (此方法调用几乎1000~10000次)

findOne(arr,[1,2]);//returns true. (I NEED THIS)
arr.includes([1,2]);//returns false.
arr[0]==[1,2];// returns false.


function findOne(arr, arr2) { 
    for(var l=0;l<arr.length;l++){
        if(arr[l][0]==arr2[0]&&arr[l][1]==arr2[1]&&arr[l][2]==arr2[2]){
           return true;
        }
    }
    return false;
}

我尝试使用arr0.include(arr1),但如果param是数组,这不起作用。 如果(arr0 == arr1)也没有用。

有谁知道解决方案?

3 个答案:

答案 0 :(得分:0)

你的解决方案不应该“非常慢”,它具有线性时间复杂性。你可以像这样检查O(1):

var lookup = {
  '1#2': true,
  '3#4': true
};
var arr = [[1, 2], [3, 4]];

function findOne(arr2) {
  return lookup[arr2.join('#')];
}

function addArray(arrayToAdd) {
  const s = arrayToAdd.join('#');
  lookup[s] = true;
  arr.push(arrayToAdd);
}

function removeAtIndex(index) {
  const s = arr[index].join('#');
  delete lookup[s];
  arr.splice(index, 1);
}

想法是保持数组arr包含的查找表。显然,这需要您在每次添加或删除项目时更新查找表,我已提供了示例。这显然会占用更多的内存,我不确定你的数组有多大,所以不确定这是不是一个问题。

查找表还假设数组项是数字,如果它们是字符串,例如,['a。','ab']。join('。')和['a','。ab' ] .join('。')会产生不需要的相同字符串,请考虑到这一点。

既然你说你多次调用它,那么可能是我们应该优化的代码。如果你想检查10k项目是否在arr中,你当前在整个阵列上迭代10000 * arraySize次,而只需一次即可。

答案 1 :(得分:0)

此处有三种可能的用例,但您尚未指定您使用的用例,因此我将同时提及这两种情况。

  • 案例1:Array1始终相同,Array2也发生了变化。在这种情况下,您可以做的是从数组中构建一个映射,并使用它来检查该值是否存在。这将需要一段时间第一次(因为你必须构建它),但如果Array1总是相同的,所有以下检查将会快得多。

一个例子:

var arr = [[1,2,3],[3,4,5]];
var arr2 = [3, 4, 5];

function buildMap(arr) {
    var retObj = {};
    for (var l=0;l<arr.length;l++) {
    retObj[arr[l][0]] = {};
    retObj[arr[l][0]][arr[l][1]] = {};
    retObj[arr[l][0]][arr[l][1]][arr[l][2]] = true;
  }

  return retObj;
}

function findOne(mapArr, arr2) { 
    return mapArr[arr2[0]][arr2[1]][arr2[2]];
}

var mapArr = buildMap(arr);

console.log(findOne(mapArr, arr2));
  • 案例2:Array1更改,Array2始终相同。你可以做同样的事情,切换两个阵列。

  • 案例3:两个阵列都发生了变化。在这种情况下你不能做太多事情,你必须至少经过主阵列一次,所以你不能低于O(n)。除非你有其他一些你没有提到的约束(我特意想到的数据是否被排序)。

答案 2 :(得分:-2)

您可以将array#somearray#every一起使用。首先遍历每个数组,然后比较两个数组的长度,只有它们相等才比较每个数组。

&#13;
&#13;
var arr = [[1,2],[3,4]];
var findOne = (matrix, arr) => {
  return matrix.some(a => a.length === arr.length && a.every((v,i) => v === arr[i]));
} 
console.log(findOne(arr,[1,2]))
&#13;
&#13;
&#13;