2

I want to compare two string arrays, but case insensitive and independent.

For the example:

['a', 'b', 'c'] === ['A', 'c', 'B'] -> TRUE

['a', 'b', 'c'] === ['a', 'b', 'd'] -> FALSE

TRUE when they are with the same length and same values (case insensitive ['A'] === ['a'] -> true) and independent, about ordering ['a', 'b'] === ['b', 'a'] -> true.

What I did for now is:

areEqual = (arr1, arr2) => {
    const equalLength = arr1.length === arr2.length;

    return arr2.every(arr2Item => {

        return arr1.includes(arr2Item.toLowerCase());

    }) && equalLength;
};

, but this is case sensitive.

I am using JS, ES6 with React.

gdfgdfg
  • 3,181
  • 7
  • 37
  • 83
  • Possible duplicate of [How to compare arrays in JavaScript?](https://stackoverflow.com/questions/7837456/how-to-compare-arrays-in-javascript) – Keno Dec 20 '18 at 18:51
  • Is this correct? `['a', 'b', 'c'] === ['a', 'c'] -> TRUE` – Alexander O'Mara Dec 20 '18 at 18:53
  • 3
    How can `['a', 'b', 'c'] === ['a', 'c'] -> TRUE` be true if `equalLength` is false? – Andy Dec 20 '18 at 18:54
  • Edited, and yes, they can't be with different values and equal :). – gdfgdfg Dec 20 '18 at 18:58
  • 1
    What is your expectation about `['a', 'a', 'b']` and `['b', 'b', 'a']`? Should they be equal? They have the same length and the same set of values, but each with different multiplicities. If you say they're equal, then shouldn't `['a', 'a', 'a', 'b']` also be equal to them? – Scott Sauyet Dec 20 '18 at 18:59
  • 3
    Your third example still says TRUE for arrays of different lengths. – T.J. Crowder Dec 20 '18 at 18:59
  • Yes, this is true `areEqual (['a', 'a', 'b'], ['b', 'b', 'a'])`, it must be `false`, but in all cases they will be with unique values. – gdfgdfg Dec 20 '18 at 19:07

2 Answers2

7

You could normalise the strings to lower case and use a Set for checking the values.

function compare(a, b) {
    const lower = s => s.toLowerCase();
    return b
        .map(lower)
        .every(Set.prototype.has, new Set(a.map(lower)));
}

console.log(compare(['a', 'b', 'c'], ['A', 'c', 'B'])); //  true
console.log(compare(['a', 'b', 'c'], ['a', 'b', 'd'])); // false
console.log(compare(['a', 'b', 'c'], ['a', 'c']));      //  true
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
1

You need to replace arr1 with a lowercase copy of it. You should also return immediately if they're not the same length, rather than going through all the comparison work when it's not necessary.

areEqualCI = (arr1, arr2) => {
    if (arr1.length != arr2.length) {
        return false;
    }
    const arr1Lower = arr1.map(e => e.toLowerCase());
    return arr2.every(arr2Item => {
        return arr1Lower.includes(arr2Item.toLowerCase());
    });
};

It might also be better to sort the two arrays, then just compare them elementwise:

areEqualCI = (arr1, arr2) => {
    if (arr1.length != arr2.length) {
        return false;
    }
    const arr1Lower = arr1.map(e => e.toLowerCase()).sort();
    const arr2Lower = arr2.map(e => e.toLowerCase()).sort();
    for (let i = 0; i < arr1.length; i++) {
        if (arr1[i] != arr2[i]) {
            return false;
        }
    }
    return true;
}
Barmar
  • 741,623
  • 53
  • 500
  • 612