在javascript中编写反函数?

时间:2013-06-29 02:31:28

标签: 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.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”子句更新原始函数,我也不必更新{{1 }}。换句话说,我不想用if语句手动构造finverse来将输出映射回输入,而是我想以某种方式操纵原始函数来得出逆。这可以在javascript中使用吗?

2 个答案:

答案 0 :(得分:3)

稍加重新分解,任务实际上非常简单。你不需要所有那些ifs,实际上,ifs运行速度比Object属性查找慢,更不用说它们没有被封存在某个私有函数中......

我们可以在没有任何流逻辑的情况下完成翻译(1英寸,1英寸输出):

// 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%确定......

答案 1 :(得分:1)

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

  1. 使用fRules中使用的规则创建名为f()的全局对象。

    fRules = [
      { 
         id: 0,
         char: ' ',
         insertPosition: 4
      },
    
      // ... other rules ...
    ];
    

    然后,您可以在fRules中使用f(),只需找到需要id的规则,然后在fInverse中迭代一系列规则并找到好的规则。现在您无需更改f(),只需更改fRules();

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