Home > Software design >  Javascript - Check array for number of occurences of value and return true or false
Javascript - Check array for number of occurences of value and return true or false

Time:11-11

I have a array of objects with the property status, where I want to return false IF

I have (zero slots with "return" or zero "ordered" status or 1 slot with "verification" or 1 "active" status)

const slots = [
  {
    status: 'void'
  },
  {
    status: 'closed'
  },
  {
    status: 'ordered'
  },
  {
    status: 'verification'
  },
  {
    status: 'active'
  }
]

I don't want to make like

x = slots.filter((val) => val.status === 'verification' || val.status === 'active'
 if (x.length > 1) return false

y = slots.filter((val) => val.status === 'return' && val.status === 'ordered')
 if (y.length > 0) return false

Is there a way to do this more efficiently and in just one "function"?

CodePudding user response:

As stated in the comments, using filter you'll still need to call the filter method more than once as your conditions are different, but you could combine it into one line like the following, with a short circuit on the conditional and (where left hand side evaluates to false) which in some cases could produce only one call to filter:

const slots = [
  {
    status: 'void'
  },
  {
    status: 'closed'
  },
  {
    status: 'ordered'
  },
  {
    status: 'verification'
  },
  {
    status: 'active'
  }
];

function checkslots(slots){
    return slots.filter((val) => val.status === 'verification' || 
        val.status === 'active').length <= 1 &&
        slots.filter((val) => val.status === 'return' && 
        val.status === 'ordered').length <= 0;
}

console.log(checkslots(slots));

CodePudding user response:

I’d be inclined to make an object out of slots and test the created properties. I think the logic is a little clearer like that, since the condition is quite complex.

const slots = [{
    status: 'void'
  },
  {
    status: 'closed'
  },
  {
    status: 'ordered'
  },
  {
    status: 'verification'
  },
  {
    status: 'active'
  }
]

function check(slots) {
  const o = Object.fromEntries(slots.map(s => [s.status, true]))

  if ((o.verification || o.active) && !o.return && !o.ordered) return false;

  return true;
}

console.log(check(slots));

CodePudding user response:

For x you can use a combination of Array#filter with Array#includes and for y a combination of Array#every and Array#includes methods as follows:

const 
   slots = [ { status: 'void' }, { status: 'closed' }, { status: 'ordered' }, { status: 'verification' }, { status: 'active' } ],
   
   x = slots
     .filter(
         ({status}) => !['verification','active'].includes(status)
     ).length === 1,
   
   y = slots
     .every(
         ({status}) => !['return', 'ordered'].includes(status)
     );
     
console.log( x, y, x || y );

CodePudding user response:

This approach calculates the count of each of the different statuses, and then applies the OR rules to those counts.

const slots = [{status:"void"},{status:"closed"},{status:"ordered"},{status:"verification"},{status:"active"}];
const c = slots.reduce((a,{status:s})=>(a[s]??=0, a[s]  , a),{});
const r = !( !c.return || !c.ordered || c.verification===1 || c.active===1 );
console.log(r);

  • Related