2

I'm trying to check an array to see if only one of the elements has data. For example this is my array:

playersByGender = {
  mens: [],
  womens: [],
  other: []
};

Any combo of these can have data as well as only one. How would I check all three and return a boolean on if only one is filled out?

I thought about using a foreach but you're not able to do that on an object.

Any help would be great, thanks!

5 Answers 5

3

Iterate the object's keys with Array#reduce, and for every array with length > 0, add 1 to the sum. Compare the final sum to get a Boolean answer.

const playersByGender = {
  mens: [],
  womens: [1, 2],
  other: []
};

const onlyOne = (obj) => Object.keys(obj).reduce((sum, k) => obj[k].length > 0 ? sum + 1 : sum, 0) === 1;

console.log(onlyOne({
  mens: [],
  womens: [1, 2],
  other: []
}));

console.log(onlyOne({
  mens: [],
  womens: [1, 2],
  other: [1]
}));

Sign up to request clarification or add additional context in comments.

2 Comments

Running into this error inside of my constructor Operator '+' cannot be applied to types 'number' and 'boolean'.
Working without issues!
2

let playersByGender = {
  mens: [],
  womens: [1,1],
  other: []
};

console.log(Object.values(playersByGender).filter(a => a.length > 0).length === 1);

Object.values returns the array of all object values, then we leave only filled arrays and count them: .filter(a => a.length > 0).length

1 Comment

Nice solution! Simple and compact.
0

You're looking for a for in loop as oppose to foreach. With the for in loop you can look over your object properties, measure the length and return if any of the object's arrays have a length.

Only 1:

var playersByGender = {
    mens: [1],
    womens: [],
    other: []
  },
  oneArrayLength = false;

for(var key in playersByGender) {
  if(playersByGender.hasOwnProperty(key)) {
    if(playersByGender[key].length) {
      if(!oneArrayLength) {
        oneArrayLength = true;
      } else {
        oneArrayLength = false;
        break;
      }
    }
  }
}

console.log(oneArrayLength);

More than 1:

var playersByGender = {
    mens: [1],
    womens: [1],
    other: []
  },
  oneArrayLength = false;

for(var key in playersByGender) {
  if(playersByGender.hasOwnProperty(key)) {
    if(playersByGender[key].length) {
      if(!oneArrayLength) {
        oneArrayLength = true;
      } else {
        oneArrayLength = false;
        break;
      }
    }
  }
}

console.log(oneArrayLength);

Edit:

I changed the above solution to match what you described in your question of only returning true when 1 of the arrays has values.

Comments

0

You can loop over the arrays, see how many are in each one, then filter out the ones that don't have any, then count them. There are lots of ways to do this as others have mentioned. I think all the answers show different methods of how you could do it. You should familiarize yourself with all the methods available to Arrays. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array

Here is another option with explanation:

let arraysWithMoreThanOne = Object.keys(playerByGender).map(function(key) {
  // starting with an array of keys men, women, other
  // the map method allows us to convert the key into something else.
  // in this case, the length of the array
  // we only care about the lengths
  return playersByGender[key].length;
}).filter(function(count) {
   // filter allows us to discard item in an array we don't care about
   // we only care if they have more than 1 in them
   return count > 0;
}) // at the end, we have converted the object into a different result
.length; // this is the number of arrays that had more than one item

Depending on your environment, some methods need polyfills to support.

Comments

0

You could indeed use a for..in loop like this:

function oneArrayHasData(arr) {
  var dataExists = false;
  for (var prop in arr) {
    if (playersByGender[prop].length) dataExists = true;
  }
  return dataExists;
}

var dataFound = oneArrayHasData(playersByGender);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.