How to perform a condition in the array to verify that multiple elements exist at the same time?

Asked

Viewed 300 times

10

I have the following array as an example:

var a = ['view', 'edit', 'insert']

And I need the following condition:

a.includes('view') // esperado: true, resultado: true
a.includes('view', 'teste') // esperado: false, resultado: true

In the second example, the value returned is true, for the value view is found, but I would like it returned false, equal to one condition AND

I tried something with indexOf, but I got the same result.

What can I do?

Note: I can have more than two parameters to compare.

3 answers

9


An efficient version:

function includesTwo(array, one, two) {
    let achou = false;
    for (const item of array) {
        if (item == one || item == two) {
            if (achou) return true;
            achou = true;
        }
    }
    return false;
}

const a = ['view', 'edit', 'insert'];
console.log(includesTwo(a, 'view', 'edit'));
console.log(includesTwo(a, 'view', 'teste'));

I put in the Github for future reference.

This shape sweeps the array only once, in addition to being more efficient for using fewer abstractions, but that part isn’t important. When you send an item to be searched in a array once and then again may have spent doubled. So it is scanning once and find the two dice at once. Make no mistake includes() and every() is a for abstracted, it has to sweep, potentially, the entire collection.

There is a detail that cannot have repeated values in array. If that can’t be guaranteed it gets a little more complicated:

function includesTwo(array, one, two) {
    let achouOne = false;
    let achouTwo = false;
    for (const item of array) {
        if (item == one) {
            if (achouTwo) return true;
            achouOne = true;
        }
        if (item == two) {
            if (achouOne) return true;
            achouTwo = true;
        }
    }
    return false;
}

const a = ['view', 'view', 'edit'];
console.log(includesTwo(a, 'view', 'edit'));
console.log(includesTwo(a, 'view', 'teste'));

I put in the Github for future reference.

Can generalize to several items if you want, I did what the question asked. To do for any number of items would have to have a loop running through the values to be searched. The more items are added the greater the distance of the efficiency. With two values to be concatenated in the search the gain is good, since it can reduce the cost by half, but in a list of large values the gain can be absurdly large, including the use of includes() and every() can become unviable already has exponential complexity in relation to the values sought, while the solution of the simple loop I gave has linear complexity in relation to the values.

The path of the stones was given in the last one. You need a control variable for each value you search for. How to do this if you can have multiple values? Simple, put in a collection. You can use a array with the key being each value starting in false and changing true when you find that.

8

Using the method includes, you can only verify if an element exists at a time, since only the first argument can be used for that purpose. See documentation to learn more.

If you want to check if several elements exist in one array, may use the AND operator (&&) explicitly. Thus:

const arr = ['view', 'edit', 'insert'];

console.log(
  arr.includes('view') && arr.includes('test')
); // false

Another option is to create a function includesAll, that encapsulates this logic:

function includesAll(arr, ...items) {
  for (const item of items) {
    if (!arr.includes(item)) {
      return false;
    }
  }
  
  return true;
}

const arr = ['view', 'edit', 'insert'];

console.log(includesAll(arr, 'view', 'edit')); // true
console.log(includesAll(arr, 'view', 'teste')); // false

The problem in using includes (or indexOf) So for every item you want to search, theoretically, a complete search in the array is performed. So, if you want to verify the existence of 4 elements in a array of 100 elements, in the worst-case scenario, you will perform 400 searches (4 * 100), that is, 100 searches for each of the 4 elements. See algorithm of includes in the specification to better understand.

One way to optimize this is to do something like:

function allIncludes(arr, elms) {
  const map = Object.create(null);

  for (const item of arr) {
    map[item] = 1;
  }

  for (const el of elms) {
    if (!map[el]) {
      return false;
    }
  }

  return true;
}

const arr = [1, 2, 3, 4, 5, 5];
console.log(allIncludes(arr, [1, 2, 3, 4])); // true
console.log(allIncludes(arr, [1, 2, 3, 4, 5])); // true
console.log(allIncludes(arr, [1, 2, 3, 4, 5, 6])); // false

Note that in this last example I did not use the notation of spread for the arguments.

  • 5

    Nothing better than good, old and guaranteed IF() well used. Congratulations, from my point of view your first code arr.includes('view') && arr.includes('test') solves, is what it should always be, without exaggerating and without creating methodologies or else find that ES6 onwards will change 100% of the language. Live the simple that works well :D (ps: for backward compatibility I suggest the indexOf() !== 1)

8

It is possible to use the function every. It checks if all conditions are true and returns true. Should any of them return false, returns false.

let a = ['view', 'edit', 'insert'];

console.log(['view', 'teste'].every(b => a.includes(a)))

console.log(['view', 'insert'].every(b => a.includes(b)))

What we did in the case was basically apply the function includes on each of the a.

We can also create a function to facilitate the work. As the other answer already teaches the creation of the function, I preferred to use Array.prototype for the array itself to have the method that performs this verification.

Behold:

Array.prototype.includesAll = function (...args) {
    return args.every(item => this.includes(item));
}

let a = ['a', 'b', 'c'];


console.log(a.includesAll('a')); // true
console.log(a.includesAll('a', 'b')); // true
console.log(a.includesAll('a', 'b', 'd')); // false

Note: Although changing the prototype directly, it is important to remember that in some cases this can cause some problems depending on the browser and the like, for example, if this function in the future was created natively in the Array.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.