RoundRobin功能方法 - 为什么我的功能有副作用?

Fla*_*nix 9 javascript functional-programming

目的

我试图以纯粹的功能方式创建循环算法(https://en.wikipedia.org/wiki/Round-robin_scheduling).

该函数应该接收如下数组:

[
    [ 1, 2 ],
    [ 3, 4 ]
]
Run Code Online (Sandbox Code Playgroud)

并产生以下输出:

[ 1, 3, 2, 4 ]

为实现这一目标,我决定以递归方式实现循环,如下所示:

const roundRobin = (arr, results) => {
    if (arr.length === 0) return results;

    const newResults = arr.reduce((acc, current) => {

        if (current.length > 0) {
            acc.results.push(current.shift());
            acc.arr.push(current);
        }
        return acc;

    }, { arr: [], results });

    return roundRobin(newResults.arr, newResults.results);
};
Run Code Online (Sandbox Code Playgroud)

在这里,我感觉到一系列结果,当我没有任何东西可以添加时,我就完成了.可以使用以下代码:

const array =     [
        [ 1, 2 ],
        [ 3, 4 ]
    ];

const result = roundRobin( array, [] );
Run Code Online (Sandbox Code Playgroud)

问题

在我的代码中,我reduce在我的arr参数中使用以确保我不修改原始代码.但是,如果我在使用roundRobin之前打印数组,之后变量就变了!我以某种方式改变它!

问题:

  1. 如果我使用reduce,这是纯粹的,我如何改变我的参数?
  2. 是否有另一种实现roundRobin的纯/功能方式?

Tha*_*you 7

  1. 如果我使用的是纯粹的 reduce,我如何改变我的参数?

函数参数不能真正改变;一个奇怪的想法 - 但我确定你的意思是提供给你的函数的参数正在发生变异。是的,.shift正如其他人指出的那样

对于它的价值,.reduce除非用户提供的 lambda 是纯的,否则它不是纯的

  1. 是否有另一种实现循环的纯/功能方式?

是的

const isEmpty = xs =>
  xs.length === 0
  
const head = ( [ x , ...xs ] ) =>
  x
  
const tail = ( [ x , ...xs ] ) =>
  xs

const append = ( xs , x ) =>
  xs.concat ( [ x ] )
  
const roundRobin = ( [ x , ...xs ] , acc = [] ) =>
  x === undefined
    ? acc
    : isEmpty ( x )
      ? roundRobin ( xs , acc )
      : roundRobin ( append ( xs , tail ( x ) )
                   , append ( acc , head ( x ) )
                   )

const data =
  [ [ 1 , 4 , 7 , 9 ]
  , [ 2 , 5 ]
  , [ 3 , 6 , 8 , 10 , 11 , 12 ]
  ]
                   
console.log ( roundRobin ( data ) )
// => [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 ]

console.log ( roundRobin ( [ [ 1 , 2 , 3 ] ] ) )
// => [ 1 , 2 , 3 ]

console.log ( roundRobin ( [] ) )
// => []
Run Code Online (Sandbox Code Playgroud)

  • 这个功能简直……太漂亮了! (2认同)
  • 如果可以的话,我会将其更改为已接受的答案。我想你应该知道... (2认同)