I want to get the array with the smallest result by multiplying all its terms.
The array will be inside another array, to work with them.
My code is:
function _min (arr){
var _reduced = arr.map(cur => {
return cur.reduce((c,i)=> {
return c * i;
});
});
return Math.min(..._reduced);
}
console.log(_min([[4,3,5],[5,2,5]]));
I get the values correctly, but how could I get to which array the lowest value obtained belongs to?
You can also make the function itself
_min
return all the information.In this example it
_min
returns an object with the value of the product, the array itself and the index of the array:In the internal array it is used
reduce
to calculate the product (as you did in the example).p
The and parametersc
correspond to the "previous" and "current" elements in each iteration. By not giving an initial value to the "previous" value in the first iterationp
, it will match the first element of the array andc
the second. From the second iteration itp
has the value calculated so far andc
the current element.The
reduce
external applies to the entire array (the array of arrays) and goes through each element to keep the one with the smallest product. In this case the "previous" value is initialized withnull
so that in the first iteration itprev
has a value ofnull
,item
("current" element) corresponds to the first array andindex
will be 0 (index of the first element).To fully understand the example, you need to understand how the
reduce
object method worksArray
. I will try to clarify it with some examples.The method
reduce
The first problem when it comes to understanding the behavior of the method
reduce
usually comes from the name that is usually given to the first two parameters that the function passes to the method receives: "previous" and "current". These names can give the impression that they are elements of the same type (such as the previous and current element of the array) when they are not."previous" refers to the value returned by the previous iteration: the result obtained so far.
"current" refers to the current element of the array being iterated over.
To try to avoid this confusion from now on I will refer to that first ("previous") parameter as "result" or "calculated result".
The other source of confusion is usually the two modes of behavior that the method has depending on whether a value is provided with which to initialize the "result" or not.
The normal mode of behavior of the method
reduce
is that it is passed the function to be executed in each iteration and a value with which to initialize the "result". In this way the method executes the function for each element of the array. In the first iteration the "calculated result" parameter contains the initialization value, in the following iterations this parameter contains the value returned by the previous iteration. In this way (following the example above) to calculate the product of all the elements of the array we would do:The second method of operation is used when the result of the first iteration is always the first element of the array. In the above case, for example, in the first iteration the first element is always returned by the seed value (which is
1
), that is, the first element.In these cases the initialization value for the "result" can be omitted. The method
reduce
then starts iterating through the second element of the array, passing the first element as the "computed result":As you can see the first "current element" is the
3
(second element of the array) and the "previous result" passed to that first iteration is the4
first element.Although the result obtained is the same, a couple of differences must be taken into account:
One fewer iteration is performed, so any additional processing done in the function will not be done for the first element. In our example the console output is different. In a real case if, for example, in the function we take advantage to validate the elements of the array, that validation will not be performed for the first element.
If the array is empty and no initialization value is provided for the result, the method fails
reduce
:We can use the same system to, for example, obtain minimum and maximum values of an array:
We could also make the "result" be, for example, the two smallest numbers. For this the result should be an object with two properties: "minor" and "second". In this case the first value of the array does not serve us as "previous result" for the second iteration so we should use the mode with seed value.
What I will do is give an initialization value with an object with the two properties with value
Infinity
in this way all the elements of the array will be less than those values:From
return
your code...Here you return the result of the Array that has the minimum result:
Here you return the position of the Array that has the minimum result:
Here you return the Array that has the minimum result:
Explanation of the procedure of your code: (For your question in the comment of this answer)
Problem: I want to obtain the array with the smallest result when multiplying all its terms.
Your code is:
The first thing you are doing inside this function (
_min
), is to generate a new array (withmap
) from another (fromarr
), and save that new resulting array in a variable (_reduced
).Note: I rearranged your code to make the presentation clearer, but it's exactly the same code.
In detail; if the input is
[ [4,3,5], [5,2,5] ]
, see that it is an array containing two arrays , then first step:[ [4,3,5], [5,2,5] ].map(cur => "cuerpo de la funcion")
The
map
means that for each element of the array , you are going to apply the function that you put inside the parentheses. The array that receives the map is the one that has a as its first element and a[4,3,5]
as its second element[5,2,5]
. Do not confuse.Your variable
cur
is the temporary name that each of the elements will have. Since there are only 2, then you will have 2 iterations. In the first iterationcur = [4,3,5]
and in the second iterationcur = [5,2,5]
.Second step, the function that you are going to apply to each array is this:
cur => cur.reduce("otra funcion")
To each array , now you perform
reduce
. What it does is convert an array to a single value . Your code would look like this:For this, for each element of each array , it executes a function. This function has two parameters. The first is
c
, that during the first iteration it will take the value of the first element, during the following ones, it will take the value of the previous result. The second parameter isi
, which during the first iteration will take the value of the second element, and in the following ones the next element among the remaining ones...If you did not understand the above, I explain with the example to make it clearer. Then you can reread the previous paragraph when you understand the example:
The same happens with the other array of
[5, 2, 5]
:Once you understand the above, you have to remember where it all came from:
Which in turn, was a function that came inside a
map
:So in your variable
_reduced
you have your new array , which is[60, 50]
. This new array is parallel to the input array,arr
.Therefore, the index of one of the arrays corresponds to the index of the other.
60
corresponds to[4,3,5]
, and50
corresponds to[5,2,5]
.Finally, what is the solution you want to return? Before what you returned was:
Which is resolved as:
Your question in this regard is why indexOf of 50 returns 1, which is the position of the array you were looking for? Now it is clearer, but if not... The development of how it would be interpreted:
Finally, if you want to get the array that contains the minimum result. Since both arrays
_reduced
andarr
are parallel , then:You can perform the same development for any input you pass. And I recommend that if you are learning, try to execute the code in each step you do, so you can see this development in a more fun and clear way :)
So you could do the following:
We create an object against which we are going to compare all the values of the array (
eg: {v: Infinity, a: null}
)For each value of the array:
eg: item.reduce((v, n) => {return v * n}
)eg: let next = {a: item, v: item.reduce...
)eg: return next.v < prev.v ? next : prev;
)Al finalizar devolvemos el arreglo del objeto cuyo valor sea menor al de todos (
eg: return arr.reduce(...).a;
).Demo