Вопрос

код:

 c = 0  
 items.each { |i|  
   puts i.to_s    
   # if c > 9 escape the each iteration early - and do not repeat  
   c++  
 }  

Я хочу получить первые 10 элементов, а затем выйти из цикла «каждый».

Чем заменить закомментированную строку?есть ли лучший подход?что-то более идиоматическое Ruby?

Это было полезно?

Решение

В то время break решение работает, я думаю, что более функциональный подход действительно подходит для этой проблемы.Вы хотите take первые 10 элементов и распечатайте их, попробуйте

items.take(10).each { |i| puts i.to_s }

Другие советы

Здесь нет ++ оператор в Ruby.Также принято использовать do и end для многострочных блоков.Изменение вашего решения дает:

c = 0  
items.each do |i|  
  puts i.to_s    
  break if c > 9
  c += 1 
end

Или также:

items.each_with_index do |i, c|  
  puts i.to_s    
  break if c > 9
end

Видеть each_with_index а также Программирование Ruby Break, Redo и Next.

Обновлять: Ответ Чака с диапазонами больше похож на Ruby, и ответ Нимродма с использованием take это даже лучше.

break работает для раннего выхода из цикла, но более идиоматично просто сделать items[0..9].each {|i| puts i}.(И если все, что вы делаете, это буквально печатаете элементы без каких-либо изменений, вы можете просто сделать puts items[0..9].)

Другим вариантом было бы

items.first(10).each do |i|
  puts i.to_s
end

Мне это кажется немного проще, чем разрыв итератора, и сначала будет возвращено только столько элементов, сколько доступно, если их недостаточно.

Другой вариант:

puts items.first(10)

Обратите внимание, что это отлично работает с массивами, содержащими менее 10 элементов:

>> nums = (1..5).to_a
=> [1, 2, 3, 4, 5]
>> puts nums.first(10)
1
2
3
4
5

(Еще одно замечание: многие люди предлагают ту или иную форму puts i.to_s, но в таком случае это не .to_s избыточный? puts автоматически позвонит .to_s на нестроке, чтобы распечатать, подумал я.Вам понадобится только .to_s если бы ты хотел сказать puts 'A' + i.to_s или т.п.)

Это похоже на то, что вы хотите?

10.times { |i|
  puts items[i].to_s
}
items.each_with_index { |i, c| puts i and break if c <= 9 }

Было задано:

Я хочу получить первые 10 элементов, а затем выйти из цикла «каждый».

Использовать throw и catch для этого с небольшими изменениями в примере:

catch(:done) do
    c = 0
    collected = []
    items.each do |item|
        collected << item
        throw(:done, collected) if c == 9 # started at 0
        c += 1
    end
    collected # if the list is less than 10 long, return what was collected
end

Просто throw наклейка :done с collected и catch который ждет :done вернется collected.

И немного «рубить» это:

catch(:done) do
    items.inject([]) do |collected, item|
        throw(:done, collected) if collected.size == 10
        collected << item # collected gets returned here and populates the first argument of this block
    end
end

Я не знаю, почему некоторые люди отказываются использовать inject и использовать reduce вместо этого (они эквивалентны), когда явно пустой массив, заданный inject([]) вводят инъекцию itemс!Во всяком случае, inject вернется collected если товаров меньше 10.

Большинство ответов пытаются ответить на вопрос, какова может быть цель вопроса, а не на то, что было задано и items.take(10) в этом случае имеет смысл.Но я могу себе представить, что хочу приобрести первые вещи, которые укладываются в мой бюджет в 100 долларов.Тогда вы можете просто:

catch(:done) do
    items.inject({items: [], budget: 100}) do |ledger, item|
        remainder = ledger[:budget] - item.price
        if remainder < 0
            throw(:done, ledger)
        else
            ledger.tap do |this|
                this[:items] << item
                this[:budget] = remainder
            end # tap just returns what is being tapped into, in this case, ledger
        end
    end
end
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top