admin管理员组

文章数量:1435859

I am learning Javascript, and I saw a function on SO for paring arrays to check if they are same. However, my current function returns false if the two arrays are [string1,string2] & [string2,string1]. Basically, the two positions are interchanged. The code is as follows:

function _pareArrays(arr1,arr2){
    var result = arr1 != null && arr2 != null && arr1.length == arr2.length && arr1.every(function(element) {
            return arr2.indexOf(element);
        });
    return result ;
}

However, I want these two arrays to be returned as same. So, I changed .every to .indexOf() and it seemed to work. But, I have a doubt, how exactly is the counter getting incremented here to make sure the parison is being done for every element? I mean, like, in C++, we do,

for (int i = 0; i < 10; i++)
    if (arr1[i] == arr2[i]
      cout<<"Elements are same\n";

Here, I have an explicit i++ which increments the counter. How does it happen in the above function?

Thanks!

I am learning Javascript, and I saw a function on SO for paring arrays to check if they are same. However, my current function returns false if the two arrays are [string1,string2] & [string2,string1]. Basically, the two positions are interchanged. The code is as follows:

function _pareArrays(arr1,arr2){
    var result = arr1 != null && arr2 != null && arr1.length == arr2.length && arr1.every(function(element) {
            return arr2.indexOf(element);
        });
    return result ;
}

However, I want these two arrays to be returned as same. So, I changed .every to .indexOf() and it seemed to work. But, I have a doubt, how exactly is the counter getting incremented here to make sure the parison is being done for every element? I mean, like, in C++, we do,

for (int i = 0; i < 10; i++)
    if (arr1[i] == arr2[i]
      cout<<"Elements are same\n";

Here, I have an explicit i++ which increments the counter. How does it happen in the above function?

Thanks!

Share Improve this question edited Dec 6, 2017 at 4:07 sarah asked Dec 6, 2017 at 3:53 sarahsarah 2472 gold badges9 silver badges19 bronze badges 6
  • 1 your first code block is total rubbish. indexOf does not take a function as an argument in any documentation I've ever read - So, I changed .every to .indexOf() when you have a flat tyre, do you replace the wheel with a banana? – Jaromanda X Commented Dec 6, 2017 at 3:56
  • I'd just create shallow copies of the arrays, sort those and then use the parison mechanism you mentioned – Phil Commented Dec 6, 2017 at 3:58
  • The _pareArrays method you've defined always returns -1. As for how the every method iterates without explicitly incrementing a counter: It's a function on the Array prototype that does the itteration automatically. developer.mozilla/en-US/docs/Web/JavaScript/Reference/… – nipuna-g Commented Dec 6, 2017 at 4:02
  • See my edited function, will the above function also not work? – sarah Commented Dec 6, 2017 at 4:07
  • @sarah See my answer again. – doubleOrt Commented Dec 6, 2017 at 10:19
 |  Show 1 more ment

3 Answers 3

Reset to default 2

Convert the array into an object instead. Convert array values into keys and their respective count as their value. This is more performant as you iterate over the arrays only once.

function pare(a, b) {
  if (a.length !== b.length) {
    return false;
  }
  let set = {};
  a.forEach((i) => {
    if (set[i] !== undefined) {
      set[i]++;
    } else {
      set[i] = 1;
    }
  });
  let difference = b.every((i) => {
    if (set[i] === undefined) {
      return false;
    } else {
      set[i]--;
      if (set[i] === 0) {
        delete set[i];
      }
      return true;
    }
  });
  return Object.keys(set) == 0 && difference;
}

The first loop on the first array initialises the the set (object), the second loop on the second array subtracts the count and removes the keys when the count hits 0. If a key is not found or if the set is not empty at the end of the procedure, then the arrays are not similar.

Your current has these issues:

  1. It will return true for these 2 arrays (I hope that you understand that this is not specific to these 2): [1, 2, 2], [1,1,2]. This problem is why I set indices to undefined after a match in my solution below.

  2. indexOf returns -1 for element's it cannot find, and any number >= 0 if it can find the element, -1 is truthy, so if an element cannot be found, your parison will return true, and 0 is falsy, so if an element is located in the first index of the second array, your method will return false (which means the whole thing will bee false, because of every...). So, you should add a ~ before the result of indexOf call: ~arr2.indexOf(element).

    See this MDN page on the Bitwise Not operator (~) and how it solves the indexOf problem I mentioned.

    I also remend that you take a look at this answer of mine on truthy/falsy values and how they interact with && and ||.


So Try this out (it's mostly your example, except there is no indexOf used and I have fixed problem #2):

function _pareArrays(arr1,arr2){
  if(!(arr1 != null && arr2 != null && arr1.length == arr2.length)) {
    return false;
  }

  /* copy the arrays so that the original arrays are not affected when we set the indices to "undefined" */
  arr1 = [].concat(arr1);
  arr2 = [].concat(arr2);

  return arr1.every(function(element, index) {
    return arr2.some(function(e, i) {
      return e === element && (arr2[i] = undefined, true);
    });
  });
}
    
var x = ["str", "boo", "str"];
var y = ["boo", "str", "str"];
var z = ["abc", "def", "ghi"]    

console.log(_pareArrays(x, y));
console.log(_pareArrays(x, z));
console.log(_pareArrays(z, z));

It won't work if the array has any undefined elements, though.

So the fastest way would be to sort both arrays, then pare each one element by element. This requires 2n * log(n) + n time rather than n2 time.

function pareArrays(arr1, arr2){
  if(arr1.length !== arr2.length) return false;

  // implement custom sort if necessary
  arr1.sort();
  arr2.sort();

  // use normal for loop so we can return immediately if not equal
  for(let i=0; i<arr1.length; i++){
    if(arr1[i] !== arr2[i]) return false;
  }

  return true;
}

本文标签: Comparing arrays in javascript where order doesn39t matterStack Overflow