4

I need to know how to solve this problem I've read from internet.

With a given array I need find all uniques elements and minus than 10. Then do the sumatory of all of them. And later multiply each array value by this number (the sumatory).

I'm assuming I can use reduce to do the sumatory and map to multiply but I don't know really how it works and I'm stuck. Also to find the unique element is not easy.

I have the entry values and expected ones.

Input, expected  
[1], [1]  
[1, 1, 2], [2, 2, 4]  
[0, 0, 1, 2, 1], [0, 0, 2, 4, 2]  
[0, 10, 1, 1, 20, 3, 40, 3], [0, 0, 0, 0, 0, 0, 0, 0]  
[0, 1, 1, 2, 4, 11], [0, 6, 6, 12, 24, 66]  
[10, 1, 1, 1], [0, 0, 0, 0]  
[10, 11, 1, 2, 3, 4], [100, 110, 10, 20, 30, 40]

I'm trying a few things, but the main problem is I don't understand the syntaxis I think. I know how to solve this iterating through a loop, but I want learn by high order functions.

This is not a school project, I'm learning about this, so I don't need only the solution, I would like to understand, thanks.

What I tried is apply map like this. And also filter and reduce

var input = [0, 0, 1, 2, 1]
var output = [0, 0, 2, 4, 2]

var map, reduce, filter;
map = input.map(multiplyFunction(first,second))

function multiplyFunction(first,second){
    return first*second
}
  • 1
    I'd suggest starting with the documentation and the examples they have: [`Array#map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map) and [`Array#reduce`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce). Try it out and come back when you're stuck. – VLAZ Nov 12 '20 at 08:17
  • 1
    "sumatory" is not a word. Do you mean "summation"? – Barmar Nov 12 '20 at 08:18
  • 3
    what does this *"and minus than 10."* mean? – Nina Scholz Nov 12 '20 at 08:19
  • I guess they mean "less than 10". – Barmar Nov 12 '20 at 08:19
  • Can you explain how `[1, 1, 2]` becomes `[2, 2, 4]`? The unique elements are `1, 2`. The sum is `3`. Multiplying each element by 3 produces `[3, 3, 6]` – Barmar Nov 12 '20 at 08:21
  • Hello, thanks and sorry for my english. Yes, it is 'summation' and 'less than 10'. –  Nov 12 '20 at 08:21
  • @Barmar, number 1 is repeated, the unique number is 2. –  Nov 12 '20 at 08:22
  • See https://stackoverflow.com/questions/5667888/counting-the-occurrences-frequency-of-array-elements for how to count element occurrences. After you do that, the unique elements are the ones with count = 1. – Barmar Nov 12 '20 at 08:24
  • Adding up all the array elements is the most common example of how to use `reduce()`. – Barmar Nov 12 '20 at 08:27
  • What kind of answer are you looking for? You said you're trying to learn so you don't want us to post the solution. But other than that, all we can do is give general hints like this. – Barmar Nov 12 '20 at 08:28
  • 2
    If you post what you've tried, we can help you fix it. But otherwise, this question is going to be closed since there's no specific question. – Barmar Nov 12 '20 at 08:29
  • Ok, sorry, I edit and post. –  Nov 12 '20 at 08:31

3 Answers3

4

You could separate the wantes result into two parts, one for getting the factor of the unique values and another to map new values with the factor.

getSumOfUnique

The factor function iterates the values and continues for unwanted values.

This function uses an object to count seen values and takes a variable for summing the unique values.

This happens in two ways:

  1. add the value if the value is never seen before
  2. subtract the value if the value is seen only once.

At the end return sum as factor for the calling function.

multiply

The mapping function gets the factor first and maps a new product with Array#map.

function getSumOfUnique(array) {
    let seen = {},
        sum = 0;
    
    for (const value of array) {
        if (value >= 10) continue;
        if (!seen[value]) {
            seen[value] = 1;
            sum += value;
            continue;
        }
        if (seen[value] === 1) {
            seen[value]++;
            sum -= value;
        }
    }
    return sum;
}

function multiply(array) {
    const factor = getSumOfUnique(array);
    return array.map(value => value * factor);
}

console.log(...multiply([1]));
console.log(...multiply([1, 1, 2]));
console.log(...multiply([0, 0, 1, 2, 1]));
console.log(...multiply([0, 10, 1, 1, 20, 3, 40, 3]));
console.log(...multiply([0, 1, 1, 2, 4, 11]));
console.log(...multiply([10, 1, 1, 1]));
console.log(...multiply([10, 11, 1, 2, 3, 4]));

Finally a functional approach by using

  • less10 for checking if a value is less than 10 for Array#filter,
  • unique for getting only unique values by checking the index of the value for filter as well,
  • add a function which adds to values, later used for Array#reduce
  • multiplyBy, an IIFE (immediately-invoked function expression) with a closure over the factor, later used for map,
  • getArray a function which holds all parts and mapps the array with a previously calculated factor.

const
    less10 = value => value < 10,
    unique = (v, _, a) => a.indexOf(v) === a.lastIndexOf(v),
    add = (a, b) => a + b,
    multiplyBy = factor => value => factor * value,
    getArray = array => array.map(multiplyBy(array
        .filter(less10)
        .filter(unique)
        .reduce(add, 0)
    ));

console.log(...getArray([1]));
console.log(...getArray([1, 1, 2]));
console.log(...getArray([0, 0, 1, 2, 1]));
console.log(...getArray([0, 10, 1, 1, 20, 3, 40, 3]));
console.log(...getArray([0, 1, 1, 2, 4, 11]));
console.log(...getArray([10, 1, 1, 1]));
console.log(...getArray([10, 11, 1, 2, 3, 4]));
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • Thank you I will check and understand this, but there is only map? –  Nov 12 '20 at 08:47
  • please see second approach. – Nina Scholz Nov 12 '20 at 09:46
  • Amazing! Thank you very much and thanks for the explanation. I can't upvote due to my reputation but three answers help me, feel free to upvote among yourselves if you want! –  Nov 12 '20 at 09:54
3

Hello and welcome to StackOverflow.

First of all, I think a good point to start to understand the syntaxis is checking the w3 examples: filter, map, reduce. Or mozilla examples: filter, map, reduce

Try these examples and try to understand each step.

Your exercise need for these three functions, so as an overview, we can define each one in this way (maybe this is so informal):

  • Filter: Use a filter to create a new array.
  • Map: Do something thorugh every value into the array (i.e. map the values from one array to another).
  • Reduce: Reduce the array to an unique element.

So... for your exercise.

The phrases itself explain what function to use. Check this:

I need find all uniques elements and minus than 10

It means: "I need to use filter with a function like return unique && x < 10."

Then do the sumatory

So... reduce to an unique element. Is like "Then do reduce with a function like return currentValue + nextValue

And later multiply each array value by this number

That's like: "And later map every value as value*=sumatory"

And that's all! Easy, right? Now let's translate into code.

Let's assuming you have an array like this: [10, 11, 1, 2, 3, 4] (the last into the example)

First you need to find the unique value and < 10 using filter.
The unique position has a trick. If you compare the first and last index for a number and it's the same value, then... is unique. So the function is like this

var array = [10, 11, 1, 2, 3, 4]
var filter = array.filter(x => (array.indexOf(x) === array.lastIndexOf(x) && x < 10))
console.log(filter) // [ 1, 2, 3, 4 ] 

But there is no only one way to do this. You can create a Set to no repeat values, count every value to get those with count=1 or whatever, is your decission. I've chosen this because I think is the best way.

The syntaxis is easy to read: For each value into the array, named x then do => the function. In this case compare the index and compare is <10.

Note that in yor example you are missing (x) => so you can't pass variables to your function.

Next step... reduce

var reduce = filter.reduce((a, b) => a + b, 0)
console.log(reduce) // 10

Easy. Use reduce into the output array.
The sintaxys here is: "With the current value a and next value b, do => the function a+b starting at 0". In other words... do the sumatory.

The last step: Map.

var map = array.map((m) => {
    return m * reduce
})
console.log(map) // [ 100, 110, 10, 20, 30, 40 ]

Here you are saying: "For every value into the array, m, do a function =>{...} where multiply by the sumatory m * reduce."

AND NOW: DO IT TOGETHER!!

Yes, the (really) last step, only replace variables for functions.

Where you see reduce put filter.reduce((a, b) => a + b, 0).
And where there is filter set array.filter(x => (array.indexOf(x) === array.lastIndexOf(x) && x < 10))

var map = array.map((m) => {
    return m * (array.filter(x => (array.indexOf(x) === array.lastIndexOf(x) && x < 10))).reduce((a, b) => a + b, 0)
})

And that's all.

Hope it helps to understand a little bit how to use the functions and how to solve these problems.

After see what have you try, check the examples and note that you need to get the variables using (var) =>.

And a snippet

var array = [10, 11, 1, 2, 3, 4]
var map = array.map((m) => {
    return m * (array.filter(x => (array.indexOf(x) === array.lastIndexOf(x) && x < 10))).reduce((a, b) => a + b, 0)
})
console.log(map)
J.F.
  • 13,927
  • 9
  • 27
  • 65
2

Welcome V.D. I am a JS noob as well but this, I think I get ;)

You wanna filter out your values first, so the Array.filter method allows you to do so without any cumbersome for loops, like this:

const array = [10, 11, 3, 20, 5];
const lesserThanTen = array.filter(element => element < 10);
console.log(lesserThanTen) //[3, 5]

the syntax of the reduce() function requires you to first define the function you want to apply to the items in your array, like this:

function myFunc(total, num) {
  return total + num; // this will return the sum of the two numbers it receives
} 
// The reduce() method applies this to the array until it is just a single value

var reducedNumbers = lesserThanTen.reduce(myFunc);

Once ou have the filtered array and the summatory, you can proceed to multiply everything by this latter number.

var x = lesserThanTen.map(multiplyBySummatory)

This should be enough for you to get there ;)

WildWilyWilly
  • 121
  • 11
  • 1
    Thanks for your answer. I can't upvote due to my reputation but three answers help me, feel free to upvote among yourselves if you want! –  Nov 12 '20 at 10:00