Jonas: Just like in other sections,
let's finish this one with a bigger challenge,
so that you can bring together
everything that you've learned about arrays
throughout this section.
And, as you're about to see,
this is probably the biggest challenge in the course so far,
but that's for a reason,
because array methods, and arrays in general,
are so important that it's really worth spending some time
on practicing your new array skills here.
But anyway, in this challenge,
we are still studying dogs.
And this time around,
Julia and Kate are trying to figure out
whether dogs are eating too much or too little food.
Now, once again,
I'm not gonna read all of these instructions here.
But first, before the tasks,
you have some formula here
for the recommended food amount,
then here, you have some more considerations,
and then, finally, these tasks here.
So it's these 10 tasks, and then some hints,
and then, as always, the test data down here.
Now, just for the first one here,
it's important to note
that we actually never did something similar
to what you have to do in this first task,
which is to loop over the array of objects down there
that I just showed you,
and do some operation on these objects,
but without creating a new array.
So again, just looping over the array,
but without doing any work.
So you need to figure out which of the array methods
is the best one to do this,
and then, well, just use that method.
So maybe you can use that summary lecture
in order to find that out, all right?
And then, you can just read for yourself
what you need to do in these different tasks.
And, just like before,
if you want the written version of all of these tasks
plus this test data here,
then please make sure to go to the final version of the code
of this section.
So there, you will have all of this.
But I can also just like
keep the cursor here a little bit,
so you can then pause the video here,
then you can read the first few tasks, and complete them,
and then in the end, you can move down here to see the rest.
So do it however suits you best.
But in any case, I see you back here in some time
once you are done with the challenge.
All right, good to see you back here.
And so let's get to work
solving these tasks here one by one.
So number one was to loop over the array of the dog objects,
and then, for each of them,
actually calculate the recommended portion
using that formula in the beginning.
But remember, we need to do this
without creating a new array,
but instead just performing some work on the dogs array.
And so, for this, all we need to do is
to use the forEach method.
So let's grab this test data,
and paste that down here.
And so, basically, what we're gonna do is
to just loop over this dogs array
using the forEach method,
and then mutate this array,
adding the recommended food to each of these items here
directly into this array,
so, again, without creating a new one.
So here each element is a dog.
And so here comes the special part.
Now we want to take this object,
so each dog is indeed one object like this,
and then we just want to add a new property to it.
So this is basically the trick
to solve this task number one.
So basically just grabbing the current object,
then adding a property
called recFood,
and then we just need to calculate that value.
So let's do dog.weight,
and then to the power of 0.75,
and then multiply the whole thing by 28.
All right, let's see what we got.
So we just log to the console, again,
our original dogs array,
and then, on there, each of them should now have
this new value.
And beautiful, there it is.
Let's just round this number here.
Let's maybe round it down.
So Math.floor,
and that looks a bit nicer and cleaner, okay?
Now task number two is to search, or to find,
the dog that belongs to Sarah,
and then log to the console
whether this dog is eating too much or too little.
Now the tricky part here is
that the owner is not simply a string,
but instead it is this array of owners.
So basically we want to now find this dog object right here,
because this one is the one where the owners include Sarah.
Actually, in the previous challenge,
we did something similar,
so maybe you still remember how to do that.
So let's create a variable called dogSarah,
or could call it sarahsDog also.
And so that's dogs.find,
and then we want the dog
where dog.owners
includes Sarah.
And then let's check out if we got the correct one.
dogSarah, like this,
and indeed, there it is.
And so now all we have to do is to check
whether the recommended food is more or less
than the current food.
So that should be pretty easy.
So let's just write a string like this,
Sarah's dog eats,
and then, here, we will have either too much or too little.
So we can use a template literal here.
So that's what we're doing.
And then, here, we're just gonna have a ternary operator
which will compare the current food
with the recommended food.
So dogSarah.curFood,
if it's greater than the recommended food,
then we will say too much,
and otherwise, too little.
So let's do that, dogSarah.recFood,
so this is the recommended food portion
that we just calculated in the first step.
So without that first step, the whole challenge falls apart.
You can't do anything then.
So in this case, here, we're gonna output much,
and otherwise, little.
All right, let's just check this.
I think it was this one right here.
And yeah, so currently it's eating 275,
and so that's definitely too much.
It's way much than the recommended portion.
Next up, our task is to create an array of all the owners
of the dogs that eat too much and that eat too little.
So that shouldn't be all too hard.
ownersTooMuch,
so we want to grab all the dogs,
and then just filter by the ones that are easing,
or eating, actually, too much.
So dog,
and then dog.curFood
is more than dog.recFood.
And then here we want to grab the owners,
so that's a map,
and then dog.owners.
So console.log, ownersTooMuch,
and okay, that's looking good already.
But what we want is just one array with all of these owners,
so not an array of arrays,
and so, for that, we can use the flat method,
or we can just use flatMap to do it all in one go.
So flatMap,
and this will give us the correct answer.
Beautiful, and now just the same thing
with the ones that are eating too little.
So just duplicating the whole thing.
Here, we just need to invert the sign,
and then TooLittle,
and there we go.
And to make this output here look a little bit nicer,
we have our task four,
where the only goal is to log to the console a nice string.
So which, basically, joins all of these names
into one string.
So that's exactly what we're gonna do.
So we're gonna log a template literal again,
and then here we just take these that we just created,
so these arrays,
and then we use the join method.
And, again, hopefully you used that summary lecture,
which told you exactly that
if you want a string out of an array,
then you can use the join method.
So that's exactly the tool that we're reaching for here.
So here, we then need to specify the separator.
So let's just start with the, so just the space,
and then here
dogs are eating too much.
Let's just see how this looks in the console.
And then Matilda, Sarah, John, Leo's dogs
are eating too much.
So here, I think in the task,
it says that there should be like an and in the middle.
And so that's very simple.
We just do it like this.
So this looks more like a real sentence here,
even though maybe it should be commas here,
like Matilda, then comma, Sarah, and so on.
And then the last one should be and Leo,
but that's a bit too much work,
and you can do that if you want,
but I'm just gonna keep it simple here,
and do the other one as well, of course, and nice.
Moving on, for task number five,
what we need to do is to log to the console
whether there is any dog that is eating
exactly the amount of food that is recommended.
So as I mentioned earlier,
whenever you see this word any,
so when what you need to do somehow includes the part any,
so you want to just find any occurrence
for which a certain condition is true,
then you probably need the some method.
So all we want to do is to log a true or false.
So let's not even create a variable here,
we just log it, or we just create that code
right here inside the log.
So we just take our dogs,
and then, as I just mentioned, we just use the some method.
And I explained many times already how it works,
so I'm not gonna go deep into it here again.
So just need to specify now a boolean here,
so a condition,
and so here we're looking at the dog,
the current food portion,
and then we want to check whether it is equal,
so exactly equal, to the recommended amount.
And so if there is only one of the dogs
for which this is true,
then the whole thing will become true.
So the result of the some method will then be true.
So in a way, this is like a big OR operator
for all the elements in the array.
So dog.recFood, and then let's see.
And true.
So let's just manually verify that.
And indeed, here we have one dog in that condition.
So this one here, the current food is 244,
and that's exactly the same as the recommended food.
Now if you wanted to check
whether all of the dogs are in this condition,
so where these two values are the same,
then we would use the every method.
And so then, of course, we would get false here.
But the task was just to do the calculation for one of them.
Next up, we need to log to the console
whether all of the dogs are eating an okay amount of food,
so not the exact same amount,
so not where the current food is exactly the same
as the recommended food,
because that's actually pretty unlikely.
And so, here, we're looking for the okay amount of food.
So up here, we have this instruction saying
that eating an okay amount means
that the current food is within a range of 10%
above and below the recommended.
So basically a floor and a ceiling of 10%
around this recommended value.
And then down here, we have this hint,
which tells us, actually, exactly how to calculate that.
So here it says that being within that range means
that the current value is greater than 90% of the value,
so that's this part,
and, at the same time, it is less than 100% of that value.
So yeah, that's exactly what said here.
So the current portion should be between 90 and 110%.
All right, and again, we need to check
whether all of the dogs are in this condition.
So, as we just saw earlier,
this is a time where we now use the every method.
So dogs.every,
and then, here, let's just write that condition
that we just saw a minute ago in that hint.
So the current food needs to be, again,
less than the recommended food
times 1.1, so that's the 110%,
so the upper ceiling,
and, at the same time, it needs to be still
greater than 90% of the recommended food,
because, otherwise, this dog is really eating
way too little.
So dog.curFood needs to be greater
than the recommended food,
and then times 90%.
All right, and here we get our result.
And so this means that not all of the dogs
are within this safe region.
So they're not all eating an okay amount of food.
Some are eating way too much,
and probably some are eating way too less.
Now, in the next step,
we will actually find out exactly which ones are okay,
because step number seven is for creating an array
that will contain all the dogs
that are actually eating an okay amount of food.
Now, in order to calculate this using a filter method,
we actually need this exact same condition.
So this exact same callback function right here.
So it doesn't make sense to just copy/paste it,
but instead, we should create a separate function for this.
So let's do that.
Let's use a simple arrow function here,
because this is just a one-liner.
So let's call this one
checkEatingOkay.
And so that's then this function here.
And then, we can just very easily plug that in here,
and we'll get the exact same result.
And with this callback function now in place,
it is really simple to, again, use a filter method
to find out which are the dogs
that are eating an okay amount of food.
So dogsEatingOkay
are simply dogs.filter,
and so, here, we now just pass in the exact same function.
So let's then just log this to the console.
And there we go.
So it's these two dogs right here.
So, of course, the one where the current food
is the same to the recommended one,
but then also this one
where this dog is eating a little bit too little,
but it's still within that safe margin.
All right, and let's keep moving,
because we're still not done.
There are still three more tasks to go.
But this is really fun, I think.
So next up, we move on into grouping.
So now we're gonna group all our dogs into three groups.
And these groups are exact, too-much, or too-little,
depending on whether this particular dog is eating
too much, or too little, or the exact amount of food
that is recommended.
So let's create a variable
dogsGrouped
ByPortion,
and then as we learned earlier,
to perform this grouping,
we use Object.groupBy.
And so then, here, we specify that callback function
from which we can basically return the different groups
that we want to create in that output object.
So the array that we want to group is, of course,
the dogs array.
And then, as the second argument,
we pass in a callback function,
which, essentially, will also loop over the dogs,
and then each of the elements is, as always, called a dog.
And then from here, we can return into which group
this particular dog should belong.
So, once again, we're gonna compare the current food
with the recommended food.
So let's say dog.curFood,
if it is more than the recommended food,
then, here, let's just return,
and here we have a typo,
then we return the string of too-much,
else if, and so now the opposite case,
so where the current food is less than the recommended one,
then we return too-little,
and, finally, in the final case,
so if both of these are false,
then that means that they are actually eating
the exact same amount.
So where recommended and current are the same.
So return this one,
and with this, we are actually done.
So remember that this is how grouping works.
We basically loop over the inputted array here,
and then we determine,
for each of the elements in the array,
which group should be returned,
so into which group the current object should be returned.
So into which group the current object,
or the current array element,
should be grouped into.
So that's why, here, we just returned these three strings.
And so it is these strings
that will become the groups in the output object.
So that's what we're gonna check now.
So dogsGroupedByPortion,
and beautiful.
So we have exact, which is that one with 244,
and then we have these two.
So checking if it's correct.
And indeed, these two values are less than the recommended,
and here, they are more than the recommended.
So everything is correct.
And we are ready to move on to the next step,
which is some more grouping.
So in this case, what we want to do is to group the dogs
by the number of owners that they have.
So this is an interesting one.
And so let's get to work.
So dogsGrouped,
and this time, ByOwners.
So, again, Object.groupBy,
again, we pass in our dogs
where each of the elements is a dog.
And so, once again, we now need to return
the name of the groups that we want to return.
Now, in this case, we don't know them beforehand
like we did here.
And so, instead,
we're just gonna calculate them dynamically here,
just like we did in one of the examples
where we first learned about this array grouping.
So back then, I think we used the account type.
At this time, all we need to do is
to calculate here the number of owners.
So we don't, of course, have this value
directly in the object,
but it is very easy to calculate.
So it's just
dog.owners
.length.
Now we actually do need a string here,
I believe, I'm not 100% sure.
So let's actually log this to the console.
Probably, it's gonna work with numbers as well,
but it's not gonna look very nice.
So dogsByOwners,
and yeah, so the keys of this object here
are simply now these numbers,
but let's make this a bit nicer.
So let's create a template literal.
So placing these inside the backticks,
this here will be inside the curly braces,
and then let's just add a -owners,
so this then is a little bit easier
to understand what's happening.
So we have these three here,
which is one owners,
and so, yeah, that's correct,
so these arrays only have one element.
Then here, these have two elements.
And this one apparently has three.
So three owners in this case, nice.
So really the possibilities
with this array grouping feature are endless.
There are just so many things you can do
with your array data structures,
so many ways of grouping them,
and it is really helpful in all kinds of applications.
But anyway, now we get to task number 10,
which is the last one.
And so here, what we need to do is to sort the dogs array
by the recommended food portion in an ascending order.
And we need to do so
without mutating the original dogs array.
So this time, we want to not touch that,
but instead create a copy.
So let's create a new variable for that,
so dogsSorted,
and so we're gonna take the dogs,
and instead of using sort,
we will do toSorted.
And now, into this method,
we need to pass in the compare function
that the sort algorithm is gonna use
to determine the sort order.
So this compare function always takes two element,
which usually we call a and b,
and then, from this function, we need to return a value
which will determine whether a will be before or after b
in the sorted array.
So we already talked about this before,
but just to recap, if we return a negative value,
then a will appear before b,
but if we return a positive value,
then a will appear after b.
And if we just return zero,
then nothing really happens,
so they will stay in the same place.
Now one nice trick that we can use,
and which we also used before to sort an array
in an ascending or a descending way,
is to just subtract one value from the other.
So let's just do a.recFood,
because those are the values that we are sorting by,
and then minus b.recFood.
So, for example, if this value here is 100,
and this one here is 200,
then the result of this whole operation here
will be minus 100,
and so this negative value will mean
that a will indeed appear before b.
And so then, by the end of this, as a result,
this subtraction-based compare function will always cause
that the smaller values will appear
at the beginning of the array,
which is exactly the ascending order
that we are looking for.
So let's see if this works by logging to the console
dogsSorted
like this,
and beautiful, that worked.
So this is the smallest one, so it appears first,
and, yeah, the values go in an ascending order.
And, of course, if we wanted a descending order,
we would just have to switch a and b here.
So using that example before,
so where this value is,
so where b.recFood is 200,
and the other one is 100,
then the result here would be 100,
which is indeed a positive value,
meaning that a should appear after b.
And so, in this case, bigger values will naturally,
basically, get to the beginning of the array,
so of the new sorted array.
And so, in this case,
what we got is exactly this.
So now we are in a descending order.
So this is a bit tricky to understand,
and it's not really that important.
What matters is that usually
we always use this subtraction-based comparison
as we did here.
So just keep in mind this kind of trick,
and then you can always play around with it
in order to get the result that you are looking for.
All right, and I think that's it for this challenge.
Let's just check.
And indeed, number 10 was the last one.
Great, so congratulations for completing this huge challenge
and also completing this huge section.
But trust me, it was really worth it,
because one of the main things you will always do
when working as a JavaScript developer is
to work with arrays.
That's really one of the main parts of the job.
And so that's why I went really, really deep into arrays
throughout this section.
So I hope it wasn't too much.
But again, even if it was, I'm sure that it was worth it.
You'll need many of these tools
throughout your professional life.
And now, if you need, just take a break,
and then once you're ready,
just meet me in the next section.
So hopefully, I see you there very soon.