简体   繁体   中英

How to compare two arrays and then return the index of the difference?

I have two arrays that I need to check the difference upon and return the index of that difference.

For example, I currently have two arrays that get updated when the input's value is changed. The newTags array gets updated whenever there is a new tag within the input, such as @testing . I need to compare the newTags array with the oldTags array and return the index of the difference.

I am currently stringifying both arrays and comparing them that way, although it is unable to return the index of the difference.

var newTags = [];
var oldTags = [];

$input.on('keyup', function () {
    var newValue = $input.val();
    var pattern = /@[a-zA-Z]+/ig;
    var valueSearch = newValue.search(pattern);

    if (valueSearch >= 0) {
        newTags = newValue.match(pattern);

        if ((newTags + "") != (oldTags + "")) {
            //Need index of difference here
            console.log(newTags, oldTags);
        }

        oldTags = newTags;
    }
});

Working example

You can use a filter to find both the different values and indexes at the same time.

JSFiddle: https://jsfiddle.net/k0uxtnkd/

Array.prototype.diff = function(a) {
    var source = this;
    return this.filter(function(i) {
        if (a.indexOf(i) < 0) {
            diffIndexes.push(source.indexOf(i));
            return true;
        } else {
            return false;
        }
    });
};
var diffIndexes = [];
var newTags = ['a','b','c'];
var oldTags = ['c'];
var diffValues = newTags.diff(oldTags);
console.log(diffIndexes); // [0, 1]
console.log(diffValues); // ['a', 'b']

To convert this to a function instead of add it to the array prototype: JSFiddle: https://jsfiddle.net/k0uxtnkd/1/

function arrayDiff(a, b) {
    return a.filter(function(i) {
        if (b.indexOf(i) < 0) {
            diffIndexes.push(a.indexOf(i));
            return true;
        } else {
            return false;
        }
    });
};
var diffIndexes = [];
var newTags = ['a','b','c'];
var oldTags = ['c'];
var diffValues = arrayDiff(newTags, oldTags);
console.log(diffIndexes); // [0, 1]
console.log(diffValues); // ['a', 'b']

You don't need to loop through both arrays, you can simply loop through both simultaneously:

var findDivergence = function (a1, a2) {
    var result = [], longerLength = a1.length >= a2.length ? a1.length : a2.length;
    for (i = 0; i < longerLength; i++){
        if (a1[i] !== a2[i]) {
            result.push(i);
        }
    }
    return result;
};

console.log(findDivergence(["a","b","c","d","e","f","g","h","i"], ["a","b","d","r","e","q","g"]));
//outputs [2, 3, 5, 7, 8]

This is significantly more efficient than double-looping or using indexOf (both of which will search the second array many more times than necessary). This also handles cases where the same item shows up more than once in a given array, though if one array is longer than the other and the longer one contains an element that is undefined, that index will count as a match.

for(var i=0; i < newTags.length; i++) {
    for(var j=0; j < oldTags.length; j++) {
        if(newTags[i] === oldTags[j]) {
            console.log("match found");
            console.log("Match found for value: " + newTags[i] + " at index in oldTags: " + j + );
         }
         else{
           console.log("match not found");
         }
    }
}

Using 2 loops you can do a quick check, in the if statements add what you want to happen.

Below is a performance comparison of three common methods to perform the task asked in this question.

const arr1 = ['A', 'B', 'C'];
const arr2 = ['A', 'D', 'C', 'E'];

// Filter indexOf
function diffArray1(a1, a2) {
  let aDiffs = [];
  a1.filter((i) => {
    if (a2.indexOf(i) < 0) {
      aDiffs.push(a1.indexOf(i));
    }
  });
  return aDiffs;
};

// Loop indexOf
function diffArray2(a1, a2) {
  let aDiffs = [];
  for (let i=0; i<a1.length; ++i) {
    if (a2.indexOf(a1[i]) < 0) {
      aDiffs.push(a1.indexOf(a1[i]));
    }
  }
  return aDiffs;
};

// Loop equality
function diffArray3(a1, a2) {
  let aDiffs = [];
  for (let i=0; i<a1.length; ++i) {
    if (a1[i] !== a2[i]) {
      aDiffs.push(i);
    }
  }
  return aDiffs;
};

diffArray1(arr2, arr1); // Returns [1, 3]
diffArray2(arr2, arr1); // Returns [1, 3]
diffArray3(arr2, arr1); // Returns [1, 3]

diffArray3() is the fastest in Chrome v102.0.5005.63 (64-bit) on my system (Intel Core i7-7700HQ 32GB RAM). diffArray1() is about 38% slower and diffArray2() is about 22.5% slower. Here's the test suite:

https://jsbench.me/59l42hhpfs/1

Feel free to fork this and add more methods; please leave the URL of the fork in the comment if you do this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM