Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/419.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用javascript编写反函数?_Javascript_Function_Lambda_Functional Programming - Fatal编程技术网

用javascript编写反函数?

用javascript编写反函数?,javascript,function,lambda,functional-programming,Javascript,Function,Lambda,Functional Programming,我今天在工作中遇到了一个情况,我需要编写我已经编写的函数的逆函数,但是我发现手动编写逆函数效率很低,因为我似乎会重复很多代码,如果我要更新原始函数,我必须用相应的更改来更新逆函数。我所说的函数如下所示: var f = function(id, str) { if (id === 0) { return str.substring(0, 4) + " " + str.substring(4, 8); } else if (id === 1) { return str.su

我今天在工作中遇到了一个情况,我需要编写我已经编写的函数的逆函数,但是我发现手动编写逆函数效率很低,因为我似乎会重复很多代码,如果我要更新原始函数,我必须用相应的更改来更新逆函数。我所说的函数如下所示:

var f = function(id, str) {
  if (id === 0) {
    return str.substring(0, 4) + " " + str.substring(4, 8);
  } else if (id === 1) {
    return str.substring(0, 3) + "/" + str.substring(3, 8);
  } else if (id === 2) {
    return str.substring(0, 4) + "-" + str.substring(4, 8);
  } else if (id == 3) {
    return str.substring(0, 3) + "," + str.substring(3, 8);
  }
}

因此,例如
f(0,“ABCDEFGH”)
将返回
“ABCD EFGH”
。我需要一个反向函数,它使用函数
f(id,str)
从输出中获得输入。所以
finverse(formattedStr)
应该返回对应输入的字典。例如,
finverse(“ABCD-EFGH”)
应该返回
{id:0,str:“ABCDEFGH”}
。是否可以利用现有函数
f
来编写此逆函数,这样即使我要用额外的“else if”子句更新原始函数,也不必更新
finverse
。换句话说,我不想用if语句手动构造
finverse
,以将输出映射回输入,而是希望以某种方式操纵原始函数以得到一个逆函数。这在javascript中可能吗?

真的没有办法让它完美地工作。这是不可能实现良好的速度特性。所以,我试着给你们两种解决这个问题的方法:

  • 使用
    f()
    中使用的规则将全局对象命名为
    fRules

    然后,您可以在
    f()
    中使用
    fRules
    简单地查找具有所需
    id
    的规则,并在
    fInverse
    中迭代规则数组并查找好的规则。现在您不需要更改
    f()
    ,只需更改
    fRules()

  • f.toString()
    获取函数文本,并将函数解析为抽象语法树。就像UglifyJs的内部功能一样。阅读更多。然后,必须根据函数语法树手动编写一些反转器。丑恶的想法


  • 通过稍微的重新分解,任务实际上相当简单。您不需要所有这些ifs,事实上,ifs的运行速度比对象属性查找慢,更不用说它们没有被封装在某个私有函数中

    我们可以在没有任何流逻辑的情况下完成转换(1 in,1+out):

    // replace all the IF logic with an externally-modifiable logic table:
    f.lut=[ [4," "], [3,"/"], [4,"-"], [3,","]  ]; //(id=index, 0=pos, 1=char)
    
    
    // simplify f() using the table to make choices instead of conditionals:
    function f(id, str) {
       id = f.lut[id];
       return str.substring(0, id[0]) + id[1] + str.substring(id[0], 8);
    }
    
    
    // use the same table in reverse to compose an inverse function:
    function finverse(s){
        return  {
           id:   +f.lut.map(function(A,i){ return A[1]==s.split(/[\w]+/).filter(Boolean)[0] ? 
                             String(i):
                             ""
                 }).filter(Boolean)[0][0], 
           str:  s.split(/[\W]+/).filter(Boolean).join('')
        };
     }
    
    
    // first, test new version of f():
     f(0, "ABCDEFGH") // ABCD EFGH
     f(1, "ABCDEFGH") // ABC/DEFGH
     f(2, "ABCDEFGH") // ABCD-EFGH
     f(3, "ABCDEFGH") // ABC,DEFGH
    
    
    // now, test the inverse:
    finverse("ABCD EFGH")   //{id:0, str:"ABCDEFGH"}
    finverse("ABC/DEFGH")   //{id:1, str:"ABCDEFGH"}
    finverse("ABCD-EFGH")   //{id:2, str:"ABCDEFGH"}
    finverse("ABC,DEFGH")   //{id:3, str:"ABCDEFGH"}
    

    如果这不是您想要的,请告诉我们,我不是100%确定…

    我不知道
    .filter(Boolean)
    速记,很好。显然,这也适用于ES6中的箭头函数:
    .filter((x)=>!!.x)
    。实际上也不需要将arg括在括号中:
    .filter(x=>!!.x)
    @cssimsek:
    .filter(x=>x)
    将实现与ES6中的
    .filter(Boolean)
    相同的效果这很好,因此无需使用
    进行强制转换;每次迭代时分配给
    x
    的值隐式转换为其布尔值。
    Array.prototype.boolFilter=function(){return Array.prototype.filter.call(this,x=>x);}从崇高到荒谬:pYou还可以使用计算机代数系统获得逆运算,因为一些JavaScript函数可以转换为数学表达式,反之亦然。
    
    // replace all the IF logic with an externally-modifiable logic table:
    f.lut=[ [4," "], [3,"/"], [4,"-"], [3,","]  ]; //(id=index, 0=pos, 1=char)
    
    
    // simplify f() using the table to make choices instead of conditionals:
    function f(id, str) {
       id = f.lut[id];
       return str.substring(0, id[0]) + id[1] + str.substring(id[0], 8);
    }
    
    
    // use the same table in reverse to compose an inverse function:
    function finverse(s){
        return  {
           id:   +f.lut.map(function(A,i){ return A[1]==s.split(/[\w]+/).filter(Boolean)[0] ? 
                             String(i):
                             ""
                 }).filter(Boolean)[0][0], 
           str:  s.split(/[\W]+/).filter(Boolean).join('')
        };
     }
    
    
    // first, test new version of f():
     f(0, "ABCDEFGH") // ABCD EFGH
     f(1, "ABCDEFGH") // ABC/DEFGH
     f(2, "ABCDEFGH") // ABCD-EFGH
     f(3, "ABCDEFGH") // ABC,DEFGH
    
    
    // now, test the inverse:
    finverse("ABCD EFGH")   //{id:0, str:"ABCDEFGH"}
    finverse("ABC/DEFGH")   //{id:1, str:"ABCDEFGH"}
    finverse("ABCD-EFGH")   //{id:2, str:"ABCDEFGH"}
    finverse("ABC,DEFGH")   //{id:3, str:"ABCDEFGH"}