Факториализировать все числа в массиве с помощью .map

У меня есть массив чисел, например. [2, 4, 5] и должен получить факториалы в новом массиве. Например. [2, 24, 120]

Как видите, я использую .map для выполнения функции над каждым целым числом в массиве, однако это не работает? Я предполагаю, что что-то не так с рекурсивной функцией?

Спасибо.

function getFactorials(nums) {

if(nums > 1){
    factarr = nums.map(x => x * (nums - 1));
}

return factarr;
}

person SirNail    schedule 12.08.2019    source источник
comment
Я не мастер математики, но факториал(4) должен быть 4*3*2*1, верно? если да, то вы этого не делаете.   -  person briosheje    schedule 12.08.2019
comment
нет факториала 4! это 4x3x2x1 :)   -  person SirNail    schedule 12.08.2019
comment
извините, это имелось в виду. Однако ваш код этого не делает;)   -  person briosheje    schedule 12.08.2019
comment
nums должен быть массивом или числом?   -  person maazadeeb    schedule 12.08.2019
comment
Я предполагаю, что что-то не так с рекурсивной функцией здесь нет рекурсивной функции.   -  person VLAZ    schedule 12.08.2019
comment
похоже, он работает для одиночных целых чисел в массиве, но не для нескольких... любая помощь приветствуется!   -  person SirNail    schedule 12.08.2019
comment
Ваш код не работает ни для одного целого числа, ни для массива. Попробуйте сначала заставить его работать с одним целым числом, а затем расширить его до массива   -  person Weedoze    schedule 12.08.2019
comment
nums — это массив типа [6] или [1,2,3]   -  person SirNail    schedule 12.08.2019


Ответы (6)


Вы можете взять функцию для факториала и отобразить значения.

Функция имеет рекурсивный стиль с проверкой значения. если значение равно нулю, функция завершается с единицей. В противном случае возвращалось произведение фактического значения и результата вызова функции с уменьшенным значением.

Проверка использует неявное приведение falsy к логическому значению для условный (тройной) оператор ?:.

const fact = n => n ? n * fact(n - 1) : 1;

var array = [2, 4, 5],
    result = array.map(fact);

console.log(result);

person Nina Scholz    schedule 12.08.2019
comment
Спасибо! я попробую это. не думал их разделять :) - person SirNail; 12.08.2019
comment
это сработало :) не могли бы вы немного подробнее объяснить, что происходит в первой строке? это было бы оценено - person SirNail; 12.08.2019
comment
@Tony fact — это функция, сигнатура которой принимает аргумент (n). Если (n) истинно (следовательно, если это не 0, в вашем конкретном сценарии), он возвращает n, умноженный на факт (n - 1), в противном случае он возвращает 1. По сути, он возвращает n * факт (n-1) рекурсивно пока n больше не соответствует действительности. - person briosheje; 12.08.2019
comment
@Nina_Scholz Тернарный оператор должен иметь это условие const fact = n => (n > 1) ? n * fact(n - 1) : 1;, иначе он может выдать StackOverlow для отрицательных чисел :) - person Vedant Terkar; 14.08.2019
comment
@VedantTerkar, factorial определен только для положительных целых чисел. - person Nina Scholz; 14.08.2019

Просто создайте функцию, которая вычисляет факториал заданного числа, а затем просто используйте ее в качестве обратного вызова для функции map.

Поскольку основной частью является способ расчета факториэля, вот два способа выполнить эту задачу.

Функция Factoriel итеративным способом:

const fact = n => {
  let f = 1,
  i = n;
  for(; i > 1; i--) f *= i;
  return f;
};

console.log(fact(4)); /** outpuut: 24 **/

Функция Factoriel рекурсивным способом:

const fact = n => n > 1 ? n * fact(n - 1) : n;

console.log(fact(4)); /** outpuut: 24 **/

И окончательный код:

const arr = [2, 4, 5],
  fact = n => n > 1 ? n * fact(n - 1) : n,
  factArr = arr.map(i => fact(i));

console.log(factArr); /** output: [2, 24, 120] **/

person ths    schedule 12.08.2019
comment
пожалуйста, не стесняйтесь просить объяснений, если это необходимо. - person ths; 12.08.2019

Вы делаете рекурсию неправильно, мой подход состоял бы в том, чтобы определить факториальный калькулятор как отдельную функцию:

function getFactorials(nums) {
  function factorial(n){
    return n === 0 ? 1 : n * factorial(n - 1);
  }
  return nums.map(x => factorial(x));
}
console.log(getFactorials([0, 1, 2, 3, 4, 5 ,6]));

person Fullstack Guy    schedule 12.08.2019

Вам нужно вычислить каждый факториал в массиве, ваш текущий код этого не делает. Рассмотрим следующий пример:

function factorial(num) {
    if (num === 0 || num === 1) {
    return 1;
  } else {
    return num * factorial(num - 1);
  }
}

const facts = [2, 4, 5];
const factsArr = facts.map(num => factorial(num));

В вашем коде вы просто умножали каждый элемент массива на сам массив.

person Furman    schedule 12.08.2019

Вместо того, чтобы делать это рекурсивно, я взял решение от @Amin Jafari, в котором используется reduce(). Эта функция быстрее, чем рекурсивное решение.

Сначала мы генерируем массив. Мы делаем это, используя Array(n + 1). n - это факториал, поэтому, например. для 6! наш n будет 6. Мы получаем индексы с помощью keys(), но Array() сам по себе возвращает только действительно пустой массив, а keys() возвращает только итератор. Поэтому мы распространяем его и помещаем результат в новый массив. Таким образом, мы имеем, например. [0,1,2,3,4,5,6] (для n + 1 с n = 6). Мы исключаем 0 с slice(1).

После этого мы, наконец, применяем reduce. Уменьшить итерации по всем элементам, применяет функцию, отслеживая аккумулятор. Нашим аккумулятором здесь является текущий продукт. Итак, что происходит, так это то, что 1 * 2 вычисляется, а результат сохраняется в a, нашем аккумуляторе. Затем мы умножаем a на следующее значение, то есть 2 * 2*, и так происходит до тех пор, пока мы не пройдем весь наш самостоятельно сгенерированный массив.

Эту функцию, основанную на reduce, мы затем можем использовать для преобразования каждого значения в нашем исходном массиве с map().

const factorial = n => [...Array(n+1).keys()].slice(1).reduce((a,c) => a * c),
      data = [2, 4, 5];

let res = data.map(v => factorial(v));

console.log(res);

person claasic    schedule 12.08.2019

Я знаю, что в этом посте уже есть много ответов, но мне, возможно, есть что добавить:

Если вы планируете часто использовать рекурсивную функцию для вычисления факториалов, допустим, вам это нужно в браузерной игре каждые 0,5 секунды, вы заметите, что она потребляет много ресурсов, в основном ваши время ????.

Мое предложение:

  • вычислить факториалы один раз
  • хранить их в состоянии приложения
  • искать их, а не вычислять их

пример кода (на основе ответа Нины Шольц):

// create this earlier, put it in the application state
const state = {lookupFact: []}

const fact = n => n ? n * fact(n - 1) : 1;

// only calculate the factorials once
function lookupFact(par) {
  if (state.lookupFact.length == 0) {
    for (var i = 0; i <= 170; i++) {
      state.lookupFact[i] = fact(i)
    }
  }
  return state.lookupFact[par]
}

// use it like this later on
console.log(lookupFact(1), lookupFact(10), lookupFact(5))

Как я уже сказал, вы должны использовать это, только если вам приходится вычислять факториалы все время.

person Thomas Pötzsch    schedule 12.08.2019