【问题标题】:how to make this code more functional and readable?如何使这段代码更具功能性和可读性?
【发布时间】:2015-12-02 16:36:03
【问题描述】:

如何使这些 javascript 语句看起来更具可读性。函数库 ramda.js 可以用来让这段代码看起来更好吗?

var getTextSpace =  function(len)
    {
            var tlength;
            if (len >= 1 && len <= 4) {
                tlength = 10;
            } else if (len === 5) {
                tlength = 14;
            } else if (len === 6) {
                tlength = 16;
            } else if (len === 7) {
                tlength = 18;
            } else if (len >= 8 && len <= 10) {
                tlength = 20;
            } else if (len === 11) {
                tlength = 22;
            } else if (len === 12) {
                tlength = 24;
            } else if (len >= 13 && len <= 15) {
                tlength = 26;
            } else if (len === 16) {
                tlength = 28;
            } else if (len >= 17 && len <= 20) {
                tlength = 32;
            } else if (len >= 21 && len <= 34) {
                tlength = tlength * 2;
            } else if (len >= 35 && len <= 80) {
                tlength = Math.round((len + len / 100 * 50));
            }
            else {
                tlength = Math.round((len + len / 100 * 30));
            }
        return tlength;
    };

提前谢谢你。

也许可以做一些允许这样做的事情?

   value
     .between(2,20).then(20)
     .between(21,22).then(0)
     .greater(25).then(25))
     .less(30).then(function(value) {return value * 20 )})

【问题讨论】:

  • 我投票结束这个问题,因为它可能属于codereview.stackexchange.com
  • 当然,但你不会得到任何答案。但我会尝试回到这里。
  • if (len &gt;= 21 &amp;&amp; len &lt;= 34) tlength = tlength * 2; 应该是tlength = tlength * 2;,不是吗?
  • 是的,这是一个错误。证明代码难以阅读。

标签: javascript functional-programming ramda.js


【解决方案1】:

Ramda 可能会有所帮助。但最主要的是以可读的方式构建你的范围。下面的代码假定输入值是整数,您不需要测试其他数字类型。这些可以完成,但是你需要比这里简单的between 更复杂的东西。您需要多个函数或一种方法来配置一个函数以确定开头和结尾中的每一个是包含还是排除。

var getTextSpace =  (function() {
  // :: (Int, Int) -> (Int -> Bool)
  var between = (begin, end) => R.both(R.gte(R.__, begin), R.lt(R.__, end));
  return R.cond([
    [between(1, 5), R.always(10)],
    [between(5, 6), R.always(14)],
    [between(6, 7), R.always(16)],
    [between(7, 8), R.always(18)],
    [between(8, 11), R.always(20)],
    [between(11, 12), R.always(22)],
    [between(12, 13), R.always(24)],
    [between(13, 16), R.always(26)],
    [between(16, 17), R.always(28)],
    [between(17, 21), R.always(32)],
    [between(21, 35), R.multiply(2)], // assuming original was typo
    [between(35, 80), len => Math.round(len + len / 100 * 50)],
    [R.T, len => Math.round(len + len / 100 * 30)]
  ]);
}());

(原来的情况下似乎有错误:

        } else if (len >= 21 && len <= 34) {
            tlength = tlength * 2;

我认为是这个意思

        } else if (len >= 21 && len <= 34) {
            tlength = len * 2;

我在这里编写了等效代码。)

您可以在 Ramda REPL 上看到这一点。

【讨论】:

  • 感谢 ramda 的实现,以及发现错误
【解决方案2】:

function getTextSpace(len) {
  // If len falls within a range then return that length
  var map = [
    [1, 4, 10],
    [5, 5, 14],
    [6, 6, 16],
    [7, 7, 18],
    [8, 10, 20],
    [11, 11, 22],
    [12, 12, 24],
    [13, 15, 26],
    [16, 16, 28],
    [17, 20, 32]
  ];


  for (var i = 0; i < map.length; i++) {
    var range = map[i];
    if (len >= range[0] && len <= range[1]) {
      return range[2];
    }
  }

  // We didn't find a range so return return calculation
  // for the following ranges.
  if (len >= 21 && len <= 34) {
    return len * 2;
  } else if (len >= 35 && len <= 80) {
    return Math.round((len + len / 100 * 50));
  }

  // Return this calculation for everything else.
  return Math.round((len + len / 100 * 30));
}

function test() {
  var out = document.getElementById("out");
  var text = "";

  for (var i = 0; i < 100; i += 3) {
    text += i + ": " + getTextSpace(i) + "\n";
  }
  out.innerHTML = text;
}

test();
&lt;pre id="out"&gt;&lt;/pre&gt;

【讨论】:

    【解决方案3】:

    您可以使用 switch 语句来避免所有 else if 语句。

    此外,如果 len 始终是整数,您可以将 tlengths 放入索引与 len 的值匹配的数组中:

    var getTextSpace = function(len) {
    
    var tlengthArray = [10,10,10,10,14,16,18,20,20,20,22,24,26,26,26,28,32,32,32,32, len*2, Math.round((len + len / 100 * 50)), Math.round((len + len / 100 * 50))];
    
    var tlength;
    
    if (len >= 1 && len <=20) {
        tlength = tlengthArray[len-1];
    }
    else if (len >= 21 && len <= 34) {
        tlength = tlengthArray[20];
    }
    else if (len >= 35 && len <= 80) {
        tlength = tlengthArray[21];
    }
    else {
        tlength = tlengthArray[22];
    }
    
    return tlength;
    
    }
    

    【讨论】:

    • 也许可以很容易地做一些能够做到的事情:value .between(2,20).then(20) .between(21,22).then(0) .greater(25) .then(25)) .less(30).then(function(value) {return value * 20 )}) .... )
    • 抱歉,不确定您的意思。
    【解决方案4】:

    Ramda 非常实用,这意味着它的最佳用途是使用尽可能多的声明性和纯函数(泛型函数,可以在许多地方使用,而不仅仅是您的代码)。我的建议是这样的代码:

    var getTextSpace = function (len) {
      var conds = [
          {range: [1, 4], result: 10},
          {range: [5, 5], result: 14},
          {range: [6, 6], result: 16},
          {range: [7, 7], result: 18},
          {range: [8, 10], result: 20},
          {range: [11, 11], result: 22},
          {range: [12, 12], result: 24},
          {range: [13, 15], result: 26},
          {range: [16, 16], result: 28},
          {range: [17, 20], result: 32},
          {range: [21, 34], result: len * 2}, // You wrote tlength * 2 but it's not defined yet so I asumed you ment len * 2
          {range: [35, 80], result: Math.round((len + len / 100 * 50))}
      ];
    
      var test = function (obj) {
        var rangeLens = R.lensProp('range');
        var range = R.view(rangeLens, obj);
    
        var lte = R.curry(R.lte)(range[0]);
        var gte = R.curry(R.gte)(range[1]);
        return R.both(lte, gte)(len);
      }
    
      var resultLens = R.lensProp('result');
      var getResult = R.curry(R.view)(resultLens);
    
      var chosen = R.find(test)(conds);
      var defIfNotFound = R.defaultTo( {result: Math.round((len + len / 100 * 30))} );
    
      return getResult(defIfNotFound(chosen));
    
    };
    

    我试图给每个函数起一个名字来解释它的作用,并将它们分成许多部分,这使得它几乎就像在读一个句子

    【讨论】:

      【解决方案5】:

      也许switch是一个替代方案。有一个帖子退出了类似的主题。

      看看here

      【讨论】:

        【解决方案6】:

        如果你想要一个普通的 JS 解决方案,这可能是一个替代方案。

        const isBetween = x => (s, e) =>
         (Number(s) <= Number(x) && Number(x) <= Number(e))
         ? true : false
        
        const getTextSpace = len => {
          const lenIsBetween = isBetween(len)
          return lenIsBetween(1,4)? 10
          : lenIsBetween(5, 5)    ? 14
          : lenIsBetween(6, 6)    ? 16
          : lenIsBetween(7, 7)    ? 18
          : lenIsBetween(8, 10)   ? 20
          : lenIsBetween(11, 11)  ? 22
          : lenIsBetween(12, 12)  ? 24
          : lenIsBetween(13, 15)  ? 26
          : lenIsBetween(16, 16)  ? 28
          : lenIsBetween(17, 20)  ? 32
          : lenIsBetween(21, 34)  ? len * 2
          : lenIsBetween(35, 80)  ? Math.round((len + len / 100 * 50))
          : Math.round((len + len / 100 * 30))
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-07-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多