Javascript 循环功能法-为什么我的功能有副作用? 客观的
我试图以纯函数的方式创建一个循环算法() 此函数应接收如下数组:Javascript 循环功能法-为什么我的功能有副作用? 客观的,javascript,functional-programming,Javascript,Functional Programming,我试图以纯函数的方式创建一个循环算法() 此函数应接收如下数组: [ [ 1, 2 ], [ 3, 4 ] ] const roundRobin = (arr, results) => { if (arr.length === 0) return results; const newResults = arr.reduce((acc, current) => { if (current.length > 0) {
[
[ 1, 2 ],
[ 3, 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, [] );
并产生以下输出:
[1,3,2,4]
代码
为了实现这一点,我决定递归地实现循环,如下所示:
[
[ 1, 2 ],
[ 3, 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, [] );
在这里,我感觉到了一系列的结果,当我没有什么可以添加的时候,我就完成了。您可以使用以下代码:
[
[ 1, 2 ],
[ 3, 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, [] );
问题
在我的代码中,我在我的arr
参数中使用reduce
,以确保我不修改原始代码。但是,如果在使用roundRobin之前和之后打印数组,则变量会更改!我不知怎么使它变异了
问题:
var array = [0, 1, 2, 3, 4];
array.shift(); // -> 0
array; // -> [1, 2, 3, 4];
最简单的方法是克隆阵列。通常可以使用来完成,但由于数组是嵌套的(虽然很简单),因此可以执行以下操作:
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), []);
在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
未捕获类型错误:无法添加/删除密封数组元素
在Array.shift()处
在到达时减少(:7:38)
在Array.reduce()处
在循环赛中(:4:28)
6点17分
您使用的是shift
,它正在改变原始数组
将其替换为Array.slice(0,1)[0]
,它将开始工作
.shift
就是这样
值得一提的是,.reduce
不是纯的,除非用户提供的lambda是纯的
const isEmpty=xs=>
xs.length==0
常数头=([x,…xs])=>
x
常数尾=([x,…xs])=>
xs
常量附加=(xs,x)=>
xs.concat([x])
常量循环=([x,…xs],acc=[])=>
x==未定义
? 行政协调会
:isEmpty(x)
? 循环赛(xs,acc)
:循环(追加(xs,尾部(x))
,附加(附件,标题(x))
)
常量数据=
[ [ 1 , 4 , 7 , 9 ]
, [ 2 , 5 ]
, [ 3 , 6 , 8 , 10 , 11 , 12 ]
]
console.log(循环(数据))
// => [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 ]
console.log(循环([[1,2,3]]))
// => [ 1 , 2 , 3 ]
console.log(循环([]))
//=>[]
shift()
会改变内部阵列我无法获取您的输入格式。你能解释一下数组数组的含义吗?尾部递归(带有一个输出参数结果发生变异)是故意的吗?如果我这样做current.slice(0,1)[0]
算法简单地停止工作:我真的不喜欢把东西转换成字符串再转换回来的想法。但我有个想法:做一个克隆人。我没有做太多的测试,但是。我相信还有其他的技术可以利用,但重要的是自由变量不是不纯的——这不是你抽象自由变量的方式;你把它作为函数的一个参数。这个函数只是。。。美丽的!我真的脸红了^ ^如果可以的话,我会把这个改成公认的答案。我想你应该知道……好吧,我终于做到了。你的答案现在是官方认可的!