DEV Community

Cover image for Let's Count Some Sheep!

Let's Count Some Sheep!

Michelle Kaplan on February 21, 2020

Having trouble falling asleep? It might be time to start counting some sheep. But, instead of counting with numbers, we're going to count the numbe...
Collapse
 
bytebodger profile image
Adam Nathaniel Davis • Edited

What you list as the "simplest way to solve this problem" is not actually the simplest solution. There is already a built-in JavaScript function that achieves this result:

const totalTrueValues = anyArray.filter(element => element === true).length;

If you want to technically meet the full requirement (which is to provide your own function that does this), then you just need to wrap the built-in JS solution in a function like:

function getTotalTrueValues(array) {
   return array.filter(element => element === true).length;
}
Collapse
 
abrjagad profile image
Abraham Jagadeesh
function getTotalTrueValues(array) {
   return array.filter(Boolean).length;
}

You may use Boolean too

Collapse
 
michellekaplan7 profile image
Michelle Kaplan

Wow, that's great Adam! I'm only 4 weeks into my studies, so I definitely have a lot more to learn. Thanks for posting this solution. I'll be using this!

Collapse
 
bytebodger profile image
Adam Nathaniel Davis

I normally wouldn't make this kinda pedantic observation, but since you say you're "only 4 weeks into studies"...

Get rid of the var. You don't want to use that in "modern" JavaScript design. You should always, always, always use let or const.

It may feel right now like that's a semantic, rather useless, observation. But it's not just based on coding dogma. JavaScript has some particular, umm... headaches regarding this and the hoisting of var-declared variables into global scope. These headaches are solved by religiously sticking with let or constant.

The full description of why var is "problematic" is far longer than I care to type in this reply. But as you get further down your studies, it's a good thing to research.

Also, FWIW, the var keyword tends to cause headaches in other languages as well (e.g., C#).

Collapse
 
ekeijl profile image
Edwin • Edited

Instead of counting sheep, how about we reduce them?

function countSheep(array) {
   return array.reduce((sum, bool) => sum + bool);
}

What's going on here? Where did the sum come from?? Adding the a boolean to a sum??? Are you nuts?!

Ok let's go step by step.

  • Reduce is an array prototype function that executes a reducer function for each of the items in the array and returns a single value.
const reducer = (accumulator, currentValue) => accumulator + currentValue;
  • The reducer function takes 2 arguments:
    • A so called accumulator, in our case it's the sum. The value that you return in the reducer function becomes the accumulator for the next iteration.
    • The value of the current iteration, our boolean!
  • We want to count total amount of times we encounter true.
    • In other words: the sum of all booleans with value true.
    • In other other words, if the value of our current iteration is true, we want to increment the sum by 1.
    • In pseudo code: sum = sum + (true ? 1 : 0).
  • So what about sum + boolean???
    • We need to use a smart little trick: if you convert a boolean to a number, then true will become 1 and false becomes 0. So Number(true) === 1.
    • If we use the addition operator +, JavaScript will automatically convert values to numbers for you!

Now, you may have noticed that we never declare sum anywhere. We never tell the reduce function to start counting at 0. Next to the reducer function, Array.reduce() can take a second parameter, which is the initial value for the accumulator. If we do not pass an initial value, it will just take the first value of our array.

There you have it!

We can just add the boolean to our sum, and it will add 1 if it is true or 0 for false, exactly what we want.

Collapse
 
michellekaplan7 profile image
Michelle Kaplan

That's so cool Edwin! Reduce sounds like a very interesting prototype that I'm going to look into more!

Collapse
 
mianashabbir profile image
Mian A Shabbir • Edited

Nice One!

You can also do this with a one-liner es6 arrow function using a JavaScript array filter method.


let sheep1 = [
  true, true, true, false,
  true, true, true, true,
  true, false, true, false,
  true, false, false, true,
  true, true, true, true,
  false, false, true, true
];

const calculateSheeps = (sheeps) => sheeps.filter(sheep => sheep === true).length;

calculateSheeps(sheep1);

You can read more about the filter method here.

Collapse
 
jasmin profile image
Jasmin Virdi • Edited

Here I have tried a different approach to this problem.
Taking sheep1 array as reference.

sheep1.sort();
let noOfTrueValues = sheep1.length - sheep1.indexOf(true);

Collapse
 
michellekaplan7 profile image
Michelle Kaplan • Edited

So many different solutions, I love it!

Collapse
 
joerter profile image
John Oerter

Fun article!

The array.splice([i], 1); line should be array.splice(i, 1). Is that what you were looking for?

Collapse
 
abrjagad profile image
Abraham Jagadeesh • Edited
sheep1.join('').match(/true/g).length

not recommended though.

Collapse
 
napicella profile image
Nicola Apicella • Edited

I dunno why, but based on the title of the post I was expecting a deep neural network which would segment sheeps in a picture and then count them XD

Collapse
 
mzaini30 profile image
Zen

You can embed REPL IT like this:

Collapse
 
michellekaplan7 profile image
Michelle Kaplan

That's a great tip, thank you! I will use that next time!