我正在尝试以纯粹的功能方式创建循环算法(https://en.wikipedia.org/wiki/Round-robin_scheduling)。
此函数应该接收如下数组:
[
[ 1, 2 ],
[ 3, 4 ]
]
并产生以下输出:
[ 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);
};
在这里,我感觉到一系列结果,当我没有任何东西可以添加时,我就完成了。可以使用以下代码:
const array = [
[ 1, 2 ],
[ 3, 4 ]
];
const result = roundRobin( array, [] );
在我的代码中,我在reduce
参数中使用了arr
,以确保我不会修改原始内容。但是,如果我在使用roundRobin之前打印数组,之后变量就变了!我以某种方式改变它!
答案 0 :(得分:4)
- 如果我使用的是reduce,那是纯粹的,我如何改变我的参数?
醇>
功能参数无法真正发生变异;一个奇怪的想法 - 但我确定你的意思是提供给你的函数的参数正在变异。是的,与其他人.shift
指出的那样
除非用户提供的lambda是纯粹的,否则.reduce
不是纯粹的
- 是否有另一种实现roundRobin的纯/功能方式?
醇>
是的
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 ( [] ) )
// => []

答案 1 :(得分:2)
Array#shift正在进行变异。
var array = [0, 1, 2, 3, 4];
array.shift(); // -> 0
array; // -> [1, 2, 3, 4];
最简单的方法是克隆数组。通常可以使用Array#concat来完成,但由于您的数组是嵌套的(虽然很简单),您可以这样做:
const roundRobin = (arr, results) => {
arr = JSON.parse(JSON.stringify(arr));
if (arr.length === 0) return results;
// ...
如果您担心全局JSON
会使函数不纯,那么您可以将其抽象出来。
const deepClone = (obj) => JSON.parse(JSON.stringify(obj));
roundRobin(deepClone(array), []);
答案 2 :(得分:1)
在JS中创建不可变对象的简单方法是使用Object.freeze
。
我创建了你的输入数组:
const array1 = Object.freeze([
Object.freeze([ 1, 2 ]),
Object.freeze([ 3, 4 ])
])
然后,当我试图调用你的函数时,我得到了:
Uncaught TypeError: Cannot add/remove sealed array elements
at Array.shift (<anonymous>)
at arr.reduce (<anonymous>:7:38)
at Array.reduce (<anonymous>)
at roundRobin (<anonymous>:4:28)
at <anonymous>:6:17
你正在使用shift
,它正在改变orignal数组。
将其替换为Array.slice(0,1)[0]
,它将开始工作。