Given an array that contains some status string,
I want to validate if the array contains at least one sleeping status and then validate if the rest of the statuses are either ok or sleeping.
So a valid array is ['ok', 'sleeping', 'sleeping', 'ok'] and an invalid array will be something like const states = ['ready', 'working','onBreak','sleeping', 'ok', 'sleeping']
What I have come up with so far is this:
const validArray = ['ok', 'sleeping', 'sleeping', 'ok'];
const isvalid = validArray.some( x => x === 'sleeping')
if(isValid){
  const canDoStuff = validArray.some( x => !['ok','sleeping'].includes(x))
  if(canDoStuff){
    doStuff()  
  }
}
Ideally, I would like to validate that in a single loop,and not two loops.
Rather than .some to check if there's one sleeping item, use .includes.
But, your other .some isn't implementing the right logic either; doStuff will only run if there's at least one item which doesn't match. Use .every instead, and check that each does match:
const validate = input => (
  input.includes('sleeping') &&
  input.every(x => ['ok', 'sleeping'].includes(x))
);
console.log(validate(['ok', 'sleeping', 'sleeping', 'ok']));
console.log(validate(['ready', 'working','onBreak','sleeping', 'ok', 'sleeping']));If you want the fastest code, use a simple for loop:
'use strict';
function isValid( array ) {
    let sleeping = false;
    for( const item of array ) {
        if( item === 'sleeping' ) {
            sleeping = true;
        } else if( item !== 'ok' ) {
            return false;
        }
    }
    return sleeping;
}
function test( array ) {
    console.log( isValid(array) ? 'Valid:' : 'Invalid:', array );
}
test( [ 'ok', 'sleeping', 'sleeping', 'ok' ] );
test( [ 'ready', 'working','onBreak','sleeping', 'ok', 'sleeping' ] );This is a bit more code than the other answers suggest, but it will be faster than any of them.
In particular, the accepted answer uses two loops, not one. You don't see the loops directly because they are hidden inside the .includes() and .every() calls.
I don't mean this as a criticism of that code - it is very clean and simple, which I always like. But when performance counts, it can help to write old-school code that lets you combine multiple loops into one.
Of course it is always wise to benchmark when performance may matter, so I took the test that @scunliffe created (thanks!) and added a test that uses this for loop: https://jsben.ch/vrzl1
If you need to support old versions of Internet Explorer, use a numeric for loop instead of the for-of loop, and var instead of let and const.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With