【问题标题】:Find missing element by comparing 2 arrays in Javascript通过比较 Javascript 中的 2 个数组来查找缺失的元素
【发布时间】:2012-03-16 11:58:49
【问题描述】:

出于某种原因,我很难解决这个问题。我需要这个 JS 函数,它接受 2 个数组,比较 2,然后返回缺少元素的字符串。例如。查找 currentArray 中缺少的元素,该元素在前一个数组中存在。

function findDeselectedItem(CurrentArray, PreviousArray){

var CurrentArrSize = CurrentArray.length;
var PrevousArrSize = PreviousArray.length;

// Then my brain gives up on me...
// I assume you have to use for-loops, but how do you compare them??

return missingElement;

}

提前致谢!我不是要代码,但即使只是朝着正确的方向推动或提示可能会有所帮助......

【问题讨论】:

  • 您需要将数组 A 的每个元素与数组 B 的每个元素进行比较。如果您知道要比较的是哪种值,则有一种方法可以加快该过程。

标签: javascript arrays compare


【解决方案1】:

问题陈述:

在 currentArray 中找到前一个数组中缺少的元素。

previousArray.filter(function(x) {  // return elements in previousArray matching...
    return !currentArray.includes(x);  // "this element doesn't exist in currentArray"
})

(这与编写两个嵌套的 for 循环一样糟糕,即 O(N2) 时间*)。如有必要,可以通过从currentArray 创建一个临时对象并将其用作 O(1) 查询的哈希表来提高效率。例如:)

var inCurrent={}; currentArray.forEach(function(x){ inCurrent[x]=true });

那么我们有一个临时查找表,例如

previousArray = [1,2,3]
currentArray = [2,3];
inCurrent == {2:true, 3:true};

那么该函数不需要每次都重复搜索currentArray,这将是一个O(N)的子步骤;它可以在 O(1) 时间内立即检查它是否在 currentArray 中。由于.filter 被调用了 N 次,因此总时间为 O(N) 而不是 O(N2):

previousArray.filter(function(x) {
    return !inCurrent[x]
})

或者,这里是for循环样式:

var inCurrent = {};
var removedElements = []
for(let x of currentArray)
    inCurrent[x] = true;
for(let x of previousArray)
    if(!inCurrent[x])
        removedElements.push(x)
        //break; // alternatively just break if exactly one missing element
console.log(`the missing elements are ${removedElements}`)

或者只是使用现代数据结构,这使得代码更加明显:

var currentSet = new Set(currentArray);
return previousArray.filter(x => !currentSet.has(x))

*(旁注:或者技术上,正如我在更一般的情况下说明的那样,其中 >1 个元素被取消选择,O(M*N) 时间)

【讨论】:

  • 这是一个绝妙的答案;一定要喜欢函数式编程。不过,还需要做一些工作才能让它在非 JS1.6 浏览器中运行。幸运的是,Mozilla 在这里的兼容性部分为我们完成了这项工作:indexOf 和这里:filter
  • 奇怪的是,虽然这个答案是最好的,但我在检查元素 === -1,而不是 !== -1 时返回了丢失的元素:在 ES6 中:previousArray. filter(prev => currentArray.indexOf(prev) === -1
  • @JeanmichelCote:啊,哎呀,我很惊讶在四年内没有人发现这一点......我误读了这个问题,认为该元素从错误的数组中丢失。已编辑。
【解决方案2】:

这应该可行。您还应该考虑数组元素实际上也是数组的情况。 indexOf 可能无法按预期工作。

function findDeselectedItem(CurrentArray, PreviousArray) {

   var CurrentArrSize = CurrentArray.length;
   var PreviousArrSize = PreviousArray.length;

   // loop through previous array
   for(var j = 0; j < PreviousArrSize; j++) {

      // look for same thing in new array
      if (CurrentArray.indexOf(PreviousArray[j]) == -1)
         return PreviousArray[j];

   }

   return null;

}

【讨论】:

  • 当我们有重复的条目说 previousArray=[5,5,7,7] 和 currentArray=[5,7,7]..returns null then 时不起作用
【解决方案3】:

看看下划线difference函数:http://documentcloud.github.com/underscore/#difference

【讨论】:

  • 哇,太好了,但它返回了什么?数组还是单个字符串变量?
  • @DeanGrobler:=&gt; [1, 3, 4] 看起来像一个数组。你为什么想要一个字符串?无论如何,您都可以轻松地将数组转换为字符串。
  • @Felix Kling - 听起来不错,只是想确定一下。谢谢:-)
  • 它返回一个数组。如果您只缺少一个元素,您可能想使用它_.difference(CurrentArray,PreviousArray)[0]。附言underscore 是一个很棒的库。我几乎在每个项目中都使用它。试一试。
  • 名称已更改为lodash,您可以在这里找到它:lodash.com/docs/4.17.15#differenceBy。非常适合 obj 数组。
【解决方案4】:

我知道这是代码,但尝试查看差异示例以了解方式:

var current = [1, 2, 3, 4],
    prev = [1, 2, 4],
    isMatch = false,
    missing = null;

var i = 0, y = 0,
    lenC = current.length,
    lenP = prev.length;

for ( ; i < lenC; i++ ) {
    isMatch = false;
    for ( y = 0; y < lenP; y++ ) {
        if (current[i] == prev[y]) isMatch = true;
    }
    if ( !isMatch ) missing = current[i]; // Current[i] isn't in prev
}

alert(missing);

或者使用ECMAScript 5 indexOf:

var current = [1, 2, 3, 4],
    prev = [1, 2, 4],
    missing = null;

var i = 0,
    lenC = current.length;

for ( ; i < lenC; i++ ) {
    if ( prev.indexOf(current[i]) == -1 ) missing = current[i]; // Current[i] isn't in prev
}

alert(missing);

而与时

var current = [1, 2, 3, 4],
    prev = [1, 2, 4],
    missing = null,
    i = current.length;

while(i) {
    missing = ( ~prev.indexOf(current[--i]) ) ? missing : current[i];
}

alert(missing);

【讨论】:

  • 使用这个我们不能得到所有缺失的元素。
【解决方案5】:

这是我的方法(也适用于重复条目):- //这里的第二个参数实际上是当前数组

function(previousArray, currentArray) {
    var hashtable=[]; 

    //store occurances of elements in 2nd array in hashtable
    for(var i in currentArray){
        if(hashtable[currentArray[i]]){
            hashtable[currentArray[i]]+=1; //add 1 for duplicate letters
        }else{
            hashtable[currentArray[i]]=1; //if not present in hashtable assign 1
        }
    }
    for(var i in previousArray){
            if(hashtable[previousArray[i]]===0 || hashtable[previousArray[i]] === undefined){ //if entry is 0 or undefined(means element not present)
                return previousArray[i]; //returning the missing element
            }
    else{
             hashtable[previousArray[i]]-=1; //reduce count by 1
        }

    }
}

逻辑是我创建了一个名为哈希表的空白数组。我们首先迭代 currentArray 并将元素用作索引,将值用作从 1 开始的计数(这有助于在存在重复条目的情况下)。然后我们遍历 previousArray 并查找索引,如果它们匹配,我们将值计数减 1。如果第二个数组的元素根本不存在,那么我们的未定义检查条件将触发并返回它。如果存在重复,则每次减 1,当遇到 0 时,该元素作为缺失元素返回。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-07
    • 2011-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多