styler
styler

Reputation: 16501

Approach for mapping a list of values with internal looping without outputting multiple values

I'm trying to functionally loop a list of numbers, checking each number against a list of rules to output an updated list consisting of numbers and strings. I'm having trouble understanding how I can combine the 2 loops without duplicating the number of items added (currently 1 * 3 iterations per number :/), I also get undefined for all entries.

Can someone point me to the technique required to achieve this, the output should be [1, 2, 'In', 4, 'Out', 'In', 7, 8, 'In', 'Out', 11, 'In', 13, 14, 'InOut']

Code:

const range = (start, end) => Array.from({ length: end }, (_, i) => i + start)
const rules = [[3, 'In'], [5, 'Out'], [15, 'InOut']]

function output(range, markers) {
  return range.map(num => {

    markers.forEach(([div, text]) => {
      if(num % div === 0) return text
      return num
    })

  })
}

output(range(1, 10), rules)

Upvotes: 2

Views: 37

Answers (1)

Matt Ellen
Matt Ellen

Reputation: 11592

You don't want to use forEach, as that is for executing a function on each element of an array, like a map that doesn't return anything.

What you should do is look for the marker, and return the substitution if you find it.

That's what find will do for you:

const range = (start, end) => Array.from({ length: end - (start-1) }, (_, i) => i + start)
const rules = [[15, 'InOut'], [5, 'Out'], [3, 'In']]

function output(range, markers) {

 return range.map(num => {

    let item = markers.find(marker => num % marker[0] === 0);
    
    if(item){
      return item[1];
    }
    return num;
  })
}

console.log(output(range(1, 30), rules))

Also, order your rules by number of divisors, so prime numbers will be at the end. This is because find takes the first hit, so you want it to find the numbers with the most divisors first.

Upvotes: 2

Related Questions