3

I'm trying to make a function that returns true if all the array values are present in an object values.

I have transformed the object values into a new array called newArray; but my question is how can I compare between the given array and the new array?

const compare = function (array, object) {
    const newArray =Object.values(object)
    //compare here and return true/false
};  

compare(["one", "two", "three"], { 0: "one", 1: "two", 2: "three" }); // => true
compare(["one", "two", "four"], { 0: "one", 1: "two", 2: "three" }); // => false
Rifat Bin Reza
  • 2,601
  • 2
  • 14
  • 29
Alaa Khalila
  • 169
  • 1
  • 11

5 Answers5

5

I transformed the object values into a new array

I think a Set would be even better, since it has a has method with sub-linear performance and the semantics are nice and clear. But the easiest way to get to a Set is via an array, so... :-)

Once you have the Set, it's a matter of looping, in this case probably with every:

const compare = (array, object) => {
    const values = new Set(Object.values(object));
    return array.every(v => values.has(v));
};

every returns true if the callback always returns a truthy value, or returns false the first time the callback returns a falsy value (short-circuiting at that point, no reason to keep looking if the answer is "no").

If you want to stick with an array, though, you could use includes in the every. It has linear performance, but in 99.9999% of situations, the performance isn't critical anyway:

const compare = (array, object) => {
    const values = Object.values(object);
    return array.every(v => values.includes(v));
};

As Nina points out, adding a check that the lengths match would short-circuit faster. Here's what that looks like for both of the above:

Set:

const compare = (array, object) => {
    const valuesArray = Object.values(object);
    if (valuesArray.length !== array.length) {
        return false;
    }
    const values = new Set(valuesArray);
    return array.every(v => values.has(v));
};

Array:

const compare = (array, object) => {
    const values = Object.values(object);
    return array.length === values.length && array.every(v => values.includes(v));
};

You could go even further and add

if (array.length === 0) {
    return true;
}

at the very beginning of both.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
3

You can sort both arrays and then check that they have the same length and loop through both at the same time comparing the two elements.

user835611
  • 2,309
  • 2
  • 21
  • 29
3

You can use Array.prototype.reduce():

const compare = (array, object) => {
    return Object.values(object).reduce((res, cur) => {
      return res && array.includes(cur);
    }, 1);
};  

console.log(compare(["one", "two", "three"], { 0: "one", 1: "two", 2: "three" })); // => true
console.log(compare(["one", "two", "four"], { 0: "one", 1: "two", 2: "three" })); // => false
Greedo
  • 3,438
  • 1
  • 13
  • 28
  • You *can*, but it doesn't short-circuit. That won't matter often, though. It also doesn't offer any semantic information to the reader, vs. `every` which calls out exactly what's being done. – T.J. Crowder Aug 26 '20 at 09:16
3

I suggest to check the length of the array and values as well.

const
    compare = (array, object) => {
        const values = Object.values(object)
        return array.length === values.length && values.every(v => array.includes(v));
    };


console.log(compare(["one", "two", "three"], { 0: "one", 1: "two", 2: "three" })); //  true
console.log(compare(["one", "two", "four"], { 0: "one", 1: "two", 2: "three" })); // false
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
1
const compare = (array, object) => Object.values(object).every(n => array.includes(n));
Tigran Abrahamyan
  • 756
  • 1
  • 4
  • 7