简体   繁体   中英

In JavaScript how to make sure that array has at least one specific element and the others meet another condition?

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 .

You can use a simple for-loop as follow:

 const validate = arr => { let foundSleeping = false; for (let str of arr) { if (!["sleeping", "ok"].includes(str)) return false; if (str === "sleeping") foundSleeping = true; } return foundSleeping; }; console.log(validate(['ok', 'sleeping', 'sleeping', 'ok'])); console.log(validate(['ready', 'working','onBreak','sleeping', 'ok', 'sleeping']));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM