2015-05-26 2 views
2

Прежде всего, я прочитал все ответы из Why doesn't Ruby support i++ or i—? и понял почему. Обратите внимание, что это не просто еще одна тема для обсуждения о том, есть ли это или нет.Ruby элегантная альтернатива ++ в вложенных циклах?

То, что я на самом деле, является более изящным решением для ситуации, которая заставила меня задаться вопросом и узнать о ++// в Ruby. Я искал петли, each, each_with_index и все так же, но я не мог найти лучшего решения для этой конкретной ситуации.

Меньше разговоры, больше коды:

# Does the first request to Zendesk API, fetching *first page* of results 
all_tickets = zd_client.tickets.incremental_export(1384974614) 

# Initialises counter variable (please don't kill me for this, still learning! :D) 
counter = 1 

# Loops result pages 
loop do 

    # Loops each ticket on the paged result 
    all_tickets.all do |ticket, page_number| 
    # For debug purposes only, I want to see an incremental by each ticket 
    p "#{counter} P#{page_number} #{ticket.id} - #{ticket.created_at} | #{ticket.subject}" 
    counter += 1 
    end 

    # Fetches next page, if any 
    all_tickets.next unless all_tickets.last_page? 

    # Breaks outer loop if last_page? 
    break if all_tickets.last_page? 

end 

В настоящем время, мне нужно counter только для отладки - это не большое дело вообще - но мое любопытство напечатало сам этот вопрос: есть ли лучше (красивое, более элегантное) решение для этого? Наличие целой строки только для counter += 1 кажется довольно скучным. Как пример, наличие "#{counter++}" при печати строки было бы намного проще (для удобства чтения, по крайней мере).

Я не могу просто использовать индекс .each, потому что это вложенный цикл, и он будет сброшен на каждой странице (внешний цикл).

Любые мысли?

КСТАТИ: Этот вопрос не имеет ничего делать с Zendesk API вообще. Я только что использовал его, чтобы лучше проиллюстрировать мою ситуацию.

ответ

0
all_tickets.each_with_index(1) do |ticket, i| 

Я не уверен, где page_number исходит от ...

Ruby Docs См.

+0

'all_tickets.next' выбирает следующую страницу результатов, автоматически присвоив его' all_tickets', поэтому необходимость перевернуть его снова. – mathielo

+0

Извините @B Семь, я ошибся '.each' с' .all' во время тестирования/отладки и написания вопроса. Фактический метод, который проходит через билеты, - '.all'. Я обновил вопрос. – mathielo

+0

Я думаю, проблема не в том, что Ruby нуждается в '++' или '--'. Чувствительность 'counter = 1' и' counter + = 1' происходит от того, что дизайн не чист. Этот код имеет две обязанности: получение билетов и их печать. Я бы использовал один цикл, чтобы получить все билеты, а другие - для печати. –

0

Как упоминалось B Seven each_with_index будет работать, но вы можете сохранить page_number, так как long_ all_tickets является контейнером кортежей, так как он должен работать прямо сейчас.

all_tickets.each_with_index do |ticket, page_number, i| 
    #stuff 
end 

Где я является индексом. Если в каждом элементе all_tickets вы добавили больше, чем билет и номер страницы, просто помните, что индекс является дополнительным и останется в конце.

+0

Извините @Pedro Ivan, я ошибся '.each' с' .all' во время тестирования/отладки и написания вопроса Фактический метод, который проходит через билеты, является '.all'. Я обновил вопрос. – mathielo

+0

Но все же индекс' each_with_index' будет сбрасываться каждый раз, когда внешний цикл _loops_. – mathielo

+0

Я не могу проверить его прямо сейчас , но попробуйте добавить all.each_with_index, поскольку .all возвращает коллекцию. –

0

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

all_tickets = *(1..10) 
inner_limit = all_tickets.size 
outer_limit = 5000 
1.upto(outer_limit) do |outer_counter| 
    all_tickets.each_with_index do |ticket, inner_counter| 
    p [(outer_counter*inner_limit)+inner_counter, outer_counter, inner_counter, ticket] 
    end 
    # some conditional to break out, in your case the last_page? method 
    break if outer_counter > 3 
end 
1

Для меня counter += 1 является прекрасным способом выразить приращение счетчика.

Вы можете начать свой счетчик на 0, а затем получить эффект, который вы хотели, написав:

p "#{counter += 1} ..." 

Но я вообще не рекомендовал бы это, потому что люди не ожидают побочных эффектов, как изменение переменной произойдет внутри строка интерполяции.

Если вы ищете что-то более элегантное, вы должны сделать Enumerator, который возвращает целые числа по одному, каждый раз, когда вы вызываете next на счетчике.

nums = Enumerator.new do |y| 
    c = 0 
    y << (c += 1) while true 
end 

nums.next # => 1 
nums.next # => 2 
nums.next # => 3 

Вместо использования Enumerator.new в приведенном выше коде, вы могли бы просто написать:

nums = 1.upto(Float::INFINITY) 
Смежные вопросы