[Ruby] Вопрос по итераторам

Dennis Vshivkov walrus на amur.ru
Пт Дек 3 17:33:58 MSK 2004


On Fri, Dec 03, 2004 at 11:55:53AM +0200, Kravchenko Sergey wrote:

 >>> Не подскажите ли - есть ли возможность внутри цикла итератора
 >>> перейти к следующему значению итерации не возвращаясь в начало
 >>> цикла? То есть, например, итерация

 >>> [ 1, "a", 2, "b", 3, "c" ].each{ |i|
 >>> ...
 >>> ### get next iteration
 >>> ...
 >>> puts (i)
 >>> }

 >>> выдавала следующую последовательность:
 >>> "a"
 >>> "b"
 >>> "c"

 >> next

 >> это аналог continue в C/C++
 >> работает в циклах while и в итерациях

 >> [ 1, "a", 2, "b", 3, "c" ].each{ |i|
 >> next if i.kind_of? Fixnum
 >> puts (i)
 >> }
 > Спасибо за ответ, но вариант с next мне не подходит.
 > Как я уже сказал, необходимо перейти к следующему значению итерации,
 > _не возвращаясь в начало цикла_
 > Насколько я понимаю, такая возможность должна быть предусмотрена в самом
 > интерпретаторе, но подобной команды я в описании языка не нашёл - возможно,
 > она всё-таки не предусмотрена. Если это действительно так - хотелось бы
 > узнать мнение народа по этому поводу. Может быть есть какой-нибудь способ
 > сделать это красиво? ;)
 > Вот другой (более точный) пример задачи:

 > output = Array.new

 > [ "a", "b", "b1", "b2", "c", "d" ].each{|i|
 >     output = [ i ]

 >     if i == "b"
 >         ### получить все следующие элементы итерации,
 >         ### начинающиеся с буквы "b" (т.е. "b1", "b2")
 >         ### и записать их в массив output
 >     end

 >     puts output.join( " " )
 > }

    Этот пример не полностью соответствует первой формулировке. Потому
что нельзя проверить значение следующего элемента, не получив его. Ну,
это детали.

 > результатом должен быть следующий выход:
 > "a"
 > "b b1 b2"
 > "c"
 > "d"

    Только без кавычек, видимо...

 > Надеюсь теперь задача более понятна.

    Ну вот, например. Видимость отсутствия перехода в начало цикла. Не знаю,
насколько это красиво... :)

#!/usr/bin/ruby
out = []
%w(a b b1 b2 c d).inject(false) { |skip, i|
  out.clear unless skip

  if i == 'b' || !out.empty? && i[0] == ?b
    out.push i
    next true
  end

  unless out.empty?
    # out готов
    puts out.join(' ')
    out.clear
  end

  out.push i

  # out готов
  puts out.push(i).join(' ')
}

    Идея понятна, я надеюсь. По-честному отсутствие возврата в начало
цикла можно замутить на Continuation. Но это будет ещё `красивей'. :)

-- 
/Awesome Walrus <walrus на amur.ru>

    P.S. Кука в тему. =)

              ...Выполняя трудную задачу, не томиться этим -- это лекарство...


Подробная информация о списке рассылки Ruby