2009-02-10 2 views
125

Я хочу использовать для-всех и счетчик:Автоматический счетчик в Ruby для каждого?

i=0 
for blah in blahs 
    puts i.to_s + " " + blah 
    i+=1 
end 

Есть ли лучший способ сделать это?

Примечание: я не знаю, если blahs массив или хэш, но приходится делать blahs[i] бы не сделать это намного сексуальнее. Также я хотел бы знать, как написать i++ в Ruby.


Технически, Мэтт и ответ Squeegy пришел в первый, но я даю лучший ответ paradoja так распространился вокруг точек немного на SO. Также в его ответе была заметка о версиях, которая по-прежнему актуальна (пока мой Ubuntu 8.04 использует Ruby 1.8.6).


Если вы использовали puts "#{i} #{blah}", который является гораздо более емким.

+0

Там нет оператора инкремента в Ruby. N + = 1, который вы написали, есть ближайший эквивалент. Он должен быть синтаксическим сахаром для n + = 1, что само по себе сокращается при n = n + 1. Идея ++ была отвергнута, поскольку она скрывает тот факт, что вы переназначаете переменную. http://rubyurl.com/Dsb1 – Chuck

+0

Ницца! Спасибо Чак. Я был вынужден изучить ++ i и i ++ в Java, поэтому я просто подумал, что он всегда будет там. –

ответ

183

Как люди говорят, вы можете использовать

each_with_index 

, но если вы хотите индексов с итератор, отличный от «каждого» (например, если вы хотите сопоставить индекс или что-то подобное), вы можете объединить счетчики с помощью метода each_with_index или просто использовать with_index:

blahs.each_with_index.map { |blah, index| something(blah, index)} 

blahs.map.with_index { |blah, index| something(blah, index) } 

Это то, что вы можете сделать с ruby ​​1.8.7 и 1.9.

+1

Стоит отметить, что это ново в 1.9. –

+1

Хорошо пятнистый. На самом деле, это также в 1.8.7, но это что-то стоит добавить. – paradoja

+0

Почему я на Ruby 1.8.6, если я только что установил все на Ubuntu? Является ли 1.8.7 экспериментальным/бета? –

10

Да, это collection.each, чтобы сделать петли, а затем each_with_index, чтобы получить индекс.

Возможно, вам стоит прочитать книгу Руби, потому что это фундаментальный рубин, и если вы этого не знаете, у вас будут большие проблемы (попробуйте: http://poignantguide.net/ruby/).

Взятые из исходного кода Ruby:

hash = Hash.new 
%w(cat dog wombat).each_with_index {|item, index| 
    hash[item] = index 
} 
hash #=> {"cat"=>0, "wombat"=>2, "dog"=>1} 
+0

Спасибо за ссылку (отлично) и ответ. –

+0

Без проблем, рад помочь. Не означало быть «средним» по отношению к блоку .each - это фундаментальные конструкции ruby ​​и их изучение на лету будет действительно, очень болезненным. :) Лучше всего укусить пулю и потратить несколько часов на чтение! –

+0

Не беспокойтесь, спасибо за ваш ответ, @Matt. –

53
[:a, :b, :c].each_with_index do |item, i| 
    puts "index: #{i}, item: #{item}" 
end 

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

+0

Ничего, я вижу точку с ограничениями синтаксисом for. Я должен привыкнуть к блокам с несколькими параметрами. –

1

Если blahs это класс, который смешивает в Enumerable, вы должны быть в состоянии сделать это:

blahs.each_with_index do |blah, i| 
    puts("#{i} #{blah}") 
end 
4

Что касается вашего вопроса о выполнении i++, ну, вы не можете этого сделать в Ruby. Утверждение i += 1, которое у вас было, это именно то, как вы должны это делать.

+0

Прохладный, спасибо, что было освещено в комментариях по вопросу ... –

6

Если у вас нет новой версии each_with_index, вы можете использовать метод zip для пары индексов с элементами:

blahs = %w{one two three four five} 
puts (1..blahs.length).zip(blahs).map{|pair|'%s %s' % pair} 

, который производит:

1 one 
2 two 
3 three 
4 four 
5 five 
+1

Где я могу найти этот код из вашего ответа ''% s% s '% [1, "two"] 'в документах Ruby? Благодарим за помощь и за сохранение вертикального пространства, используя одну линию для записи и отображения. –

+1

В этом контексте оператор% -sign является методом класса String. Вы можете прочитать об этом по адресу http://ruby-doc.org/core/classes/String.html#M000770. Или вы можете ввести ri String #% в командной строке. Или вы можете набрать ri%, чтобы увидеть все документированные классы, которые его распознают, например, более знакомое значение в ri Fixnum #%. – George

1

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

.each_with_index 

Адрес: п пример, чтобы показать, как .each_with_index работы:

range = ('a'..'z').to_a 
length = range.length - 1 
range.each_with_index do |letter, index| 
    print letter + " " 
    if index == length 
     puts "You are at last item" 
    end 
end 

Это будет печатать:

a b c d e f g h i j k l m n o p q r s t u v w x y z You are at last item 
Смежные вопросы