如何在Coffeescript中实现array.any()
和array.all()
方法?
答案 0 :(得分:17)
这些实际上是Javascript 1.6的一部分,并且在CoffeeScript中的工作原理相同。您需要some和every。
我不知道你在哪个环境,但IE< 9似乎不支持这些方法。它们很容易添加。这些页面上有一段代码显示兼容性代码,如果您愿意,可以将它们翻译成CoffeeScript,尽管您don't have to。
更粗糙,更简单的方法是(未经测试):
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
但这些都没有短路逻辑。 编辑:但请参阅里卡多的答案以获得更好的版本。
答案 1 :(得分:12)
短路(优化)版本:
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
时运行。
答案 2 :(得分:6)
结帐underscore.js,它为您提供将在任何主要JS环境中运行的_.any
和_.all
方法(a.k.a。_.some
和_.every
)。以下是underscore.coffee中CoffeeScript的实现方式:
_.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
只会引发异常。)
答案 3 :(得分:0)
我今天看着这个并决定实施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
因为我发现它是可读的。另外,我只是将其作为自由浮动函数而不是数组方法。