Как реализовать методы array.any () и array.all () в Coffeescript? - PullRequest
11 голосов
/ 23 августа 2011

Как реализовать методы array.any() и array.all() в Coffeescript?

Ответы [ 4 ]

17 голосов
/ 23 августа 2011

Они на самом деле являются частью Javascript 1.6 и будут работать точно так же в CoffeeScript. Вы хотите некоторые и каждый .

Я не знаю, в какой среде вы находитесь, но IE <9, похоже, не поддерживает эти методы. Их довольно легко добавить. На этих страницах есть фрагмент кода, который показывает вам код совместимости, и если вы хотите, вы можете перевести их на CoffeeScript, хотя вам <a href="http://jashkenas.github.com/coffee-script/#embedded" rel="noreferrer"> не нужно .

Более грубый, более простой способ (непроверенный):

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

Но ни у одного из них нет логики короткого замыкания. Редактировать : Но см. Ответ Рикардо, чтобы найти лучшую их версию.

12 голосов
/ 24 августа 2011

Версии с коротким замыканием (оптимизированные):

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.

6 голосов
/ 23 августа 2011

Проверьте underscore.js , который предоставляет вам методы _.any и _.all (также известные как _.some и _.every), которые будут работать в любой основной среде JS.Вот как они реализованы в CoffeeScript в underscore.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, который простовыдает исключение.)

0 голосов
/ 14 марта 2015

Я смотрел на это сегодня и решил реализовать 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 таким образом, потому что нашел его читабельным. Кроме того, я просто сделал это как свободно плавающую функцию вместо метода массива.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...