Странное поведение метода Reduce в JavaScript? - PullRequest
1 голос
/ 30 апреля 2020

Я пытался создать массив четных чисел ряда Фибоначчи, используя функциональное программирование - код ниже

let a = [1, 2];

const r = (n) =>
  Array.from(
    a[a.length - 1] + a[a.length - 2] <= n ?
    a.push(a[a.length - 1] + a[a.length - 2]) && r(n) :
    a
  )
  .filter(v => !(v % 2))
  //.reduce((s, v) => s+=v, 0)

console.log(r(56))

Это дает правильный массив, но когда я хотел вычислить сумму (используя метод Reduce, комментируя последнюю строку), он дает 0 в результате

let a = [1, 2];

const r = (n) =>
  Array.from(
    a[a.length - 1] + a[a.length - 2] <= n ?
    a.push(a[a.length - 1] + a[a.length - 2]) && r(n) :
    a
  )
  .filter(v => !(v % 2))
  .reduce((s, v) => s+=v, 0)

console.log(r(56))

в Repl.it (ссылка - https://repl.it/@rahul4sap / 1) . Тем не менее, когда я пытаюсь вставить то же самое в Chrome Dev инструменты, это дает правильный вывод. Может кто-нибудь, пожалуйста, помогите мне объяснить, почему различное поведение в Chrome Dev Tool и Repl.it (то же самое поведение, которое я вижу на локальном сервере Node)

Кроме того, было бы хорошо, если кто-то, пожалуйста, помогите мне исправить это как хорошо (пожалуйста, обратите внимание, что я хотел решить эту проблему максимально функциональным способом)

Заранее спасибо!

Ответы [ 3 ]

2 голосов
/ 30 апреля 2020

Вы можете сначала разделить функции и dget массив Фибоначчи, а затем отфильтровать массив и т. Д.

Этот подход использует рекурсию, передавая новый массив сборки.

const
    add = (a, b) => a + b,
    f = (n, a = [1, 2]) => a[a.length - 1] + a[a.length - 2] < n
        ? f(n, [...a, a[a.length - 1] + a[a.length - 2]])
        : a,
    r = n => f(n)
        .filter(v => !(v % 2))
        .reduce(add, 0);

console.log(r(56));
0 голосов
/ 30 апреля 2020

Рассмотрим простую рекурсивную функцию, fibs -

const fibs = (n = 0, a = 0, b = 1) =>
  n <= 0
    ? []
    : [ a, ...fibs(n - 1, b, a + b) ]
    
console.log(fibs(10)) // first 10 fib numbers
// [ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 ]

Теперь добавьте свой .filter -

const fibs = (n = 0, a = 0, b = 1) =>
  n <= 0
    ? []
    : [ a, ...fibs(n - 1, b, a + b) ]

const evens =
  fibs(10)
    .filter(n => !(n & 1))

console.log(evens)
// [ 0, 2, 8, 34 ]

Теперь добавьте свой .reduce -

const fibs = (n = 0, a = 0, b = 1) =>
  n <= 0
    ? []
    : [ a, ...fibs(n - 1, b, a + b) ]

const sumEvens =
  fibs(10)
    .filter(n => !(n & 1))
    .reduce((r, n) => r + n, 0)
    
console.log(sumEvens)
// 44

Чтобы увидеть, как вы можете вычислить Фибоначчи, используя другие методы функционального программирования, см. это недавние вопросы и ответы


Спасибо вам за это. Но я ищу вставку элемента в массив (возможно, в одну функцию), пока не будет выполнено определенное условие (например, создайте массив Фиббоначи, пока последний элемент не станет меньше 100).

Вы измените n = 0 на until = 0 и измените условие выхода вашего l oop с n <= 0 на a > until -

const fibs = (until = 0, a = 0, b = 1) =>
  a > until
    ? []
    : [ a, ...fibs(until, b, a + b) ]

console.log(fibs(100))
// [ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89 ]

const sumEvens =
  fibs(100)
    .filter(n => !(n & 1))
    .reduce((r, n) => r + n, 0)

console.log(sumEvens)
// 4
0 голосов
/ 30 апреля 2020

Вы можете получить результат в одну строку, если знаете, сколько чисел Фибоначчи вам нужно. Например, этот код фильтрует четные числа из первых 10 чисел Фибоначчи и вычисляет их сумму:

let arr = (n) => [1, 2, ...Array(n-2)].reduce((acc, rec, idx) => (idx < 2) ? [...acc, rec] : [...acc, (acc[idx-2] + acc[idx-1])],[])
.filter(it => !(it % 2))
.reduce((s, v) => s+=v, 0)

console.log(arr(10))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...