如何在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
是因为我发现它是可读的。此外,我只是把它作为一个自由浮动函数,而不是一个数组方法。