为了账号安全,请及时绑定邮箱和手机立即绑定

在接受数字或数组作为 args 的函数中,如何有效地操作这些 args 而不管类型如何?

在接受数字或数组作为 args 的函数中,如何有效地操作这些 args 而不管类型如何?

开满天机 2021-11-18 17:15:23
假设您有一个函数,它接受 1D 坐标、2D 坐标或 3D 坐标作为参数。在函数调用时,如果用户想传递一些一维坐标,他们会传递简单的数字,例如:myFunction(30, 50);但是如果他们想传递 2D 或 3D 坐标,他们会将这些坐标作为数组/向量值传递,例如:myFunction([30, 40], [50, 60]);现在,在函数定义中,假设您要运行涉及传递的坐标的各种操作和方程。因为您需要处理两种不同的 arg 类型(数字与数组)中的一种,所以您可能希望针对每种数据类型对语句进行不同的格式化,因此最终可能会重复一堆语句,这是低效的。为了论证起见,假设您不能对数组 args 进行简单的向量数学运算,而是需要循环并按索引将它们分解:function myFunction( coord1, coord2 ) {    let myVar1 = 0, myVar2 = 0, myVar3 = 0;    // if args are arrays    if ( Array.isArray( coord1 ) ) {        myVar1 = [], myVar2 = [], myVar3 = [];        for (let i = 0; i < coord1.length; i++) {            myVar1[i] = coord1[i] * coord2[i];            myVar2[i] = myVar1[i] / coord2[i] + myVar1[i];            myVar3[i] = coord1[i] * (coord2[i] / myVar2[i]);        }    // else if args are scalar    } else {        myVar1 = coord1 * coord2;            // this        myVar2 = myVar1 / coord2 + myVar1;   // is        myVar3 = coord1 * (coord2 / myVar2); // inefficient    }    return myVar3;}上面的等式是无稽之谈,但它们只是为了说明。您将如何避免在这里重复自己?我可以想到几种 DRY 方法(将标量 args 分配给单索引数组;或者将大块的方程变成混乱且难以阅读的“逻辑或”表达式(例如,myVar[i] = (coord1[i] || coord1) * (coord2[i] || coord2));或者装配一个对象数组或者什么),但我真的不喜欢其中任何一个,而且我还是个新手,所以我不知道它是什么我不知道。任何有经验的编码人员都想权衡处理这种情况的最佳实践吗?
查看完整描述

3 回答

?
慕神8447489

TA贡献1780条经验 获得超1个赞

对于逐元素重复,只需让数组函数调用标量函数:


function myFunctionArr(coords1, coords2) {

    const results = [];

    for (let i = 0; i < coords1.length; i++) {

        results[i] = myFunctionScalar(coords1[i], coords2[i]);

    }

    return results;

}

function myFunctionScalar(coord1, coord2) {

    const myVar1 = coord1 * coord2;

    const myVar2 = myVar1 / coord2 + myVar1;

    return coord1 * (coord2 / myVar2);

}

当然你也可以把它变成一个重载函数,比如


function myFunction(coord1, coord2) {

    if (Array.isArray(coord1)) { // args are arrays

        return myFunctionArr(coord1, coord2);

    } else { // args are scalar

        return myFunctionScalar(coord1, coord2);

    }

}

您甚至可以在辅助函数(也由许多具有功能的库提供)中的多个数组元素上抽象函数的元素应用:


return zipWith(myFunctionScalar, coords1, coords2)


查看完整回答
反对 回复 2021-11-18
?
慕田峪9158850

TA贡献1794条经验 获得超7个赞

如果您的泛型函数应该始终具有同构参数和返回类型,那么首先仅使用原语为您的函数定义基本情况,然后使用包装函数遍历您的参数并将您的基本情况函数应用于每个元素:


function myFunction (coord1, coord2) {

  const myVar1 = coord1 * coord2;

  const myVar2 = myVar1 / coord2 + myVar1;

  return coord1 * (coord2 / myVar2);

}


function generic (f) {

  return function g (x, ...args) {

    return Array.isArray(x)

      ? x.map((el, i) => g(el, ...args.map(arg => arg[i])))

      : f(x, ...args);

  };

}


const myGenericFunction = generic(myFunction);


console.log(myGenericFunction(30, 50));

console.log(myGenericFunction([30, 40], [50, 60]));

console.log(myGenericFunction([[30, 40], [70, 80]], [[50, 60], [10, 20]]));


查看完整回答
反对 回复 2021-11-18
?
弑天下

TA贡献1818条经验 获得超8个赞

定义每个方程的函数。


function myFunction( coord1, coord2 ) {

    // Equations

    let e1 = (a,b) => {return a * b;}

    let e2 = (a,b,c) => {return a * b + c;}

    let e3 = (a,b,c) => {return a * (b / c);}


    let myVar1 = 0, myVar2 = 0, myVar3 = 0;


    // if args are arrays

    if ( Array.isArray( coord1 ) ) {

        myVar1 = [], myVar2 = [], myVar3 = [];


        for (let i = 0; i < coord1.length; i++) {

            myVar1[i] = e1(coord1[i], coord2[i]);

            myVar2[i] = e2(myVar1[i],coord2[i],myVar1[i]);

            myVar3[i] = e3(coord1[i],coord2[i],myVar2[i]);

        }


    // else if args are scalar

    } else {

        myVar1 = e1(coord1,coord2);            // this

        myVar2 = e2(myVar1,coord2,myVar1);   // is

        myVar3 = e3(coord1,coord2,myVar2); // inefficient

    }


    return myVar3;

}


查看完整回答
反对 回复 2021-11-18
  • 3 回答
  • 0 关注
  • 147 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信