Coffeescript - 改进增加分组的算法

时间:2012-10-27 21:11:54

标签: coffeescript

下面的代码有效,但我想知道是否有更好的方法可能会使用我不熟悉的coffeescript的一些功能。

问题在于,我需要分页项目,但每次都会增加分页。

如果我以数字20为例,它将创建以下页面:

1 - 3 4 - 7 8 - 15 16 - 20

我有以下测试和代码确实通过:

module 'Remainder',
  setup: ->
    @remainder = 20

test 'splits remainder incrementally', ->
  parts = @remainder.increasingSplit()
  equal parts[0], '1 - 3', ''
  equal parts[1], '4 - 7', ''
  equal parts[2], '8 - 15', ''
  equal parts[3], '16 - 20', ''

Number.prototype.increasingSplit = ->
  start = 1
  nextSplit = 3
  parts = []
  finished = false
  while !finished
    if nextSplit > @
      parts.push "#{start} - #{@}"
      break

    parts.push "#{start} - #{nextSplit}"
    start = nextSplit + 1
    nextSplit = nextSplit * 2 + 1

  parts

1 个答案:

答案 0 :(得分:1)

如果不太多改变算法,你可以试试这个:

Number::increasingSplit = ->
  start = 1
  nextSplit = 3
  parts = []
  while start <= @
    parts.push "#{start} - #{Math.min nextSplit, @}"
    start = nextSplit + 1
    nextSplit = nextSplit * 2 + 1
  parts

变化是:

  • .prototype替换为::
  • 删除finished变量(由于break无效而未被有效使用)和break并且将条件更改为start <= @
  • 仅使用一个parts.push <part>,最小值在nextSplit@之间。

另外,我建议不要在这种情况下扩展数字原型。扩展原始类型的原型有时会导致奇怪的问题,例如:

Number::isFour = -> @ is 4
console.log 4.isFour() # -> false

这是因为在函数@内部将是一个Number 对象而不是一个原始数字,因此=== 4比较总是失败。如果将isFour定义为独立函数,则不会发生这种情况:

isFour = (n) -> n is 4
console.log isFour 4 # -> true

所以,我更喜欢这个版本的incrasingSplit

increasingSplit = (n) ->
  start = 1
  nextSplit = 3
  parts = []
  while start <= n
    parts.push "#{start} - #{Math.min nextSplit, n}"
    start = nextSplit + 1
    nextSplit = nextSplit * 2 + 1
  parts

最后,如果你不介意递归,你可以使用更多FP风格的算法:)

increasingSplit = (n, start = 1, nextSplit = 3) ->
  if start > n
    []
  else
    part = "#{start} - #{Math.min nextSplit, n}"
    rest = increasingSplit n, nextSplit + 1, nextSplit * 2 + 1
    [part, rest...]