How to compare an array of strings in Javascript?
Asked Answered
D

7

8

I want to see if two arrays of strings are equal.

Eg:

compare(["abc", "def"], ["def", "abc"])

should return true and similarly,

compare(["abc", "def"], ["def", "ghi"]) 

should return false.

What is the best way to do this?

Disordered answered 22/1, 2016 at 7:25 Comment(3)
Please provide the code where your are attempting thisRoundlet
Either sort the arrays and compare a[n] to b[n], or skip sorting and look for a[n] in every position of b.Omer
Possible duplicate of How to compare arrays in JavaScript?Potaufeu
L
6
JSON.stringify(array1.sort()) === JSON.stringify(array2.sort())
Labiodental answered 3/1, 2020 at 15:55 Comment(2)
very cool for primitives, but watch out for many pitfalls masteringjs.io/tutorials/fundamentals/compare-arraysDysarthria
This is potentially terrible for performance, for example when you're executing your function many times like on hover or on scroll.Bulwark
F
5

JavaScript doesn't have a Set or Multiset data structure (at least, not one with wide browser support), which is what you'd normally use for testing that two sets of items are the same regardless of order. So I recommend sorting the arrays and checking that their contents are equal. If you know the arrays contain only strings, you can check the items with simple equality:

function compare(array1, array2) {
  if (array1.length != array2.length) {
    return false;
  }

  array1 = array1.slice();
  array1.sort();
  array2 = array2.slice();
  array2.sort();

  for (var i = 0; i < array1.length; i++) {
    if (array1[i] != array2[i]) {
      return false;
    }
  }

  return true;
}

console.log(compare(["abc", "def"], ["def", "abc"])); // true
console.log(compare(["abc", "def"], ["def", "ghi"])); // false

For more general cases, you'll need a more complex definition of equality, and I recommend browsing the answers to this question.

Facer answered 22/1, 2016 at 7:32 Comment(5)
I think you have a problem with the logic in if (array1[i] != array2[i]) { return false; }. You don;t want to break if match not found, you should keep looking a matchPileus
it looks they have to be considered equals if they contain the same items, even if in a different order. This won't pass your check. Gonna be a n^2 iteration... or will need sorting as you implemented.Rhiannonrhianon
Thank You for the answer. Is this the most efficient way? Doesn't JS have any built in function for this operation?Disordered
I think I addressed your comments. I originally misread the question and expected the arrays to be exactly equal. Now I use the same approach as Culme and sort the arrays.Facer
Abhijith: I usually use this approach. In extreme cases I will put all the items from array1 as keys in an Object (the closest thing JavaScript has to a Set data structure) to get constant-time lookup when iterating through array2, but I've hardly ever needed to.Facer
E
3

Naive algorithm: O(N^2)

function compare(array1, array2){
  for (var i = 0; i < array1.length; i++){
    if (array2.indexOf(array1[i]) < 0) return false;
  }
  return true;  
}

Better one: (uses sorting, O(NLOGN))

function compare(array1, array2){
  array1.sort();
  array2.sort();
  for (var i = 0; i < array1.length; i++){
    if (array1[i] !== array2[i]) return false;
  }
  return true;  
}
Empyrean answered 22/1, 2016 at 7:41 Comment(1)
Both of these need if(array1.length !== array2.length) { return false } at the start for them to work.Cuman
S
2

I would suggest following ES6-oneliner

const compare = (a1, a2) =>
  (a1 = new Set(a1)) &&
  (a2 = new Set(a2)) &&
  a1.size === a2.size &&
  [...a1].every(v => a2.has(v));
  1. Remove duplicates by converting arrays to Sets (for compare(['a', 'a'], ['a', 'b']) should return false).
  2. Length comparison (for compare(['a', 'b'], ['a', 'b', 'c']) should return false).
  3. Check if the first set items are present in the second set.
Socket answered 14/1, 2019 at 17:11 Comment(2)
This would return true for a1 = ['foo', 'foo'] and a2 = ['foo', 'bar'];Motherless
@StephenHarris Thank you! I applied Set converting to resolve duplicates situation.Socket
D
0

Unified solution:

function compare(a, b){
      var isEqual = false;  
      if (Array.isArray(a) && Array.isArray(b) && a.length == b.length){
          a.sort();
          b.sort();
          var i;
          for (i = 0; i < arr1.length; i++){
              if (a[i] === b[i]){
                  isEqual = true;
              } else{
                  isEqual = false;
                  break;
              }
          }

      }
      return isEqual;
}

var arr1 = ["def", "abc"], arr2 = ["abc", "def"];
console.log(compare(arr2,arr1)); // gives 'true'

console.log(compare(["abc", "def"], ["def", "ghi"])); // gives 'false'

https://jsfiddle.net/ob7e5ye5/4/

Dasi answered 22/1, 2016 at 7:45 Comment(0)
S
0
function compare(arr1, arr2){
    var match = true
    if(arr1.length != arr2.length){
        match = false
    }
    arr1 = arr1.slice();
    arr1.sort();
    arr2.slice();
    arr2.sort();
    for(var i = 0; i < arr1.length; i++){
        if(arr1[i] != arr2[i]){
            match = false;
        }
    }
    return match;
}

console.log(compare(["abc", "def"], ["def", "abc"])); // it will return true
console.log(compare(["abc", "def"], ["def", "ghi"])); // it will return false
Silvie answered 22/1, 2016 at 7:59 Comment(0)
R
0

Verbose typescript example for ordered or unordered
(obviously inspired by @dhilts answer above)

const VERBOSE = console.log // ()=>void

const areDeduplicatedArraysEqualUnordered = (a1: any[] | Set<any>, a2: any[] | Set<any>) => {
    (a1 = new Set(a1)); (a2 = (new Set(a2))); VERBOSE('checking arrays as Sets', { a1, a2 })
    return !!(a1.size === a2.size && [...a1].every(v => (a2 as Set<any>).has(v)))
}
const areDeduplicatedArraysEqualOrdered = (a1: any[], a2: any[]) => {
    (a1 = [...(new Set(a1))] as any[]) && (a2 = [...(new Set(a2))] as any[]) && VERBOSE('checking deduplicated arrays', { a1, a2 })
    return !!(a1.length === a2.length && a1.every((v: any, i) => a2[i] === v))
}

const a2 = [3,5,8]
const a1 = [8,5,3]
const notEqual = areDeduplicatedArraysEqualOrdered(a1,a2)
const yesEqual = areDeduplicatedArraysEqualUnordered(a1,a2)
VERBOSE('results', { notEqual, yesEqual})
Romelda answered 5/8, 2023 at 9:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.