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之前和之后打印数组,则变量会更改!我不知怎么使它变异了

问题:
  • 如果我使用的是纯reduce,那么我如何改变我的参数呢
  • 是否有另一种实现循环的纯/功能性方法
  • 正在进行变异

    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]
    ,它将开始工作

  • 如果我使用的是纯reduce,那么我如何改变我的参数呢
  • 函数参数不能真正变异;一个奇怪的想法——但我相信您的意思是提供给函数的参数正在发生变化。是的,正如其他人所指出的那样,
    .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]
    算法简单地停止工作:我真的不喜欢把东西转换成字符串再转换回来的想法。但我有个想法:做一个克隆人。我没有做太多的测试,但是。我相信还有其他的技术可以利用,但重要的是自由变量不是不纯的——这不是你抽象自由变量的方式;你把它作为函数的一个参数。这个函数只是。。。美丽的!我真的脸红了^ ^如果可以的话,我会把这个改成公认的答案。我想你应该知道……好吧,我终于做到了。你的答案现在是官方认可的!