如何在Coffeescript中实现array.any()和array.all()方法



如何在Coffeescript中实现array.any()array.all()方法?

这些实际上是Javascript 1.6的一部分,并且在CoffeeScript中工作相同。你想要一些和每一个。

我不知道你在什么环境,但是IE <9似乎不支持这些方法。它们很容易添加。在这些页面上有一小段代码显示你的兼容性代码,如果你想,你可以把它们翻译成CoffeeScript,虽然你不需要。

更简单的方法是(未经测试):

if not Array.prototype.some
    Array.prototype.some = (f) -> (x for x in @ when f(x)).length > 0
if not Array.prototype.every
    Array.prototype.every = (f) -> (x for x in @ when f(x)).length == @length

但是它们都没有短路逻辑。编辑:但请参阅Ricardo的回答以获得更好的版本

短路(优化)版本:

Array.prototype.some ?= (f) ->
  (return true if f x) for x in @
  return false
Array.prototype.every ?= (f) ->
  (return false if not f x) for x in @
  return true

?=是"存在分配",只有当该属性为null/undefined时才运行。

查看underscore.js,它为您提供了_.any_.all方法(也称为_.some_.every),可以在任何主要的JS环境中运行。下面是它们在CoffeeScript中的实现方式:下划线。coffee:

_.some = (obj, iterator, context) ->
  iterator ||= _.identity
  return obj.some iterator, context if nativeSome and obj.some is nativeSome
  result = false
  _.each obj, (value, index, list) ->
    _.breakLoop() if (result = iterator.call(context, value, index, list))
  result
_.every = (obj, iterator, context) ->
  iterator ||= _.identity
  return obj.every iterator, context if nativeEvery and obj.every is nativeEvery
  result = true
  _.each obj, (value, index, list) ->
    _.breakLoop() unless (result = result and iterator.call(context, value, index, list))
  result

(这些依赖于_.each,这是一个直接的迭代方法,_.breakLoop,它只是抛出一个异常。)

我今天正在看这个,并决定实现all作为折叠,我想你也可以为any做同样的事情(但它不会短路,要么):

all = (someArray, predicate) ->
  reduceAll = (left, right) ->
    return left and right
  return [predicate(elem) for elem in someArray].reduce(reduceAll, true)

非短路any将大致相似:

reduceAny = (left, right) ->
    return left or right
[p(elem) for elem in someArray].reduce(reduceAny, false)

我这样做all是因为我发现它是可读的。此外,我只是把它作为一个自由浮动函数,而不是一个数组方法。

最新更新