1

I was trying to create an even number array of Fibonacci series using Functional Programming - below code

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))

It is giving correct array but when I wanted to calculate the sum (using reduce method by commenting the last line) it is giving 0 as a result

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))

in Repl.it (Link - https://repl.it/@rahul4sap/1). However, when I try to paste the same in Chrome Dev tools it is giving correct output. Can someone please help me explain why different behavior in Chrome Dev tool and Repl.it (same behaviour I see in local Node server)

Also, it will be good if someone please help me in fixing this as well (Please note I wanted to solve this in as much Functional way as possible)

Thanks in advance!

VLAZ
  • 26,331
  • 9
  • 49
  • 67
Rahul
  • 143
  • 2
  • 16
  • Please put all relevant code here, in the question, so it's self-contained. – VLAZ Apr 30 '20 at 08:51
  • 2
    Don't mix and match imperative code `+=` with functional idioms. –  Apr 30 '20 at 08:54
  • Why are you using `Array.from()`? What are you hoping to achieve with it? – Steve Bennett Apr 30 '20 at 09:00
  • OK, I see the problem. You have a recursive function that *expects* an array back. However, if you add the `.reduce` at the end, your *recursive call* would produce plain numbers, so you brake the functionality. Thus, the top level `reduce` is only executed over an empty array. – VLAZ Apr 30 '20 at 09:05
  • Thanks for pointing the issue VLAZ and @Steve Bennett. Is there any way we can get the result in a functional programming way for this – Rahul Apr 30 '20 at 10:00

3 Answers3

1

You could separate the functions an dget the fibonacci array first and then filter the array, and so on.

This approach uses a recursion by handing over a new build array.

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));
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • Thanks! But, I am looking for a solution in a single function (probably using recursion). Will you give it a try – Rahul Apr 30 '20 at 10:04
  • 1
    @Rahul a single function isn't going to cut it. Well, unless you count one *visible* function as one function - you can have a recursive helper function defined inside which is not visible outside,. – VLAZ Apr 30 '20 at 10:42
0

You may receive result in one line when you know how many fibonacci numbers do you need. For example this code filter even numbers from the first 10 fibonacci numbers and calculate their sum:

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))
Sergio-fm
  • 46
  • 3
  • Thanks Sergio. Agree!! But in my case I don't know the numbers. It should be dynamic like push Fibbonaci number in an array until a condition is true. – Rahul May 01 '20 at 05:55
0

Consider a simple recursive function, 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 ]

Now add your .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 ]

Now add your .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

To see how you can compute fibonacci using other functional programming techniques, see this recent Q&A


Thank you for this. But I am looking for pushing element in an array (probably in a single function) until certain condition is met (like create Fibbonacci array until the last element is less than 100).

You change n = 0 to until = 0 and change the exit condition of your loop from n <= 0 to 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
Mulan
  • 129,518
  • 31
  • 228
  • 259
  • Thank you for this. But I am looking for pushing element in an array (probably in a single function) until certain condition is met (like create Fibbonacci array until the last element is less than 100). – Rahul May 01 '20 at 07:57
  • Hi Rahul, answers here can be adapted to meet your specific needs. Small changes like the one you requested is a matter of changing the exit condition of the `fibs` function provided. I made an edit that shows what you could've easily done on your own. – Mulan May 01 '20 at 14:31