Автоматичний лічильник в Ruby для кожного?


134

Я хочу використовувати для кожного і лічильник:

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

Чи є кращий спосіб це зробити?

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


Технічно відповідь Метта та Клікі спочатку прийшла, але я даю найкращу відповідь на парадою, тому трохи поширюйтесь навколо балів. Також у його відповіді була примітка про версії, яка все ще актуальна (поки мій Ubuntu 8.04 використовує Ruby 1.8.6).


Якщо ви використовували puts "#{i} #{blah}", це набагато більш лаконічний.


У Ruby немає оператора приросту. N + = 1, який ви записали, є найближчим еквівалентом. Це повинно бути синтаксичним цукром для n + = 1, що саме є скороченням для n = n + 1. Ідея ++ була відхилена, оскільки вона приховує той факт, що ви перепризначаєте змінну. rubyurl.com/Dsb1
Чак

Приємно! Дякую Чак. Мене змусили вивчати ++ i та i ++ на Java, тому я просто думав, що це завжди буде.
Dan Rosenstark

Відповіді:


190

Як люди сказали, ви можете використовувати

each_with_index

але якщо ви хочете, щоб індекси з ітератором відрізнялися від "кожного" (наприклад, якщо ви хочете зіставити індекс чи щось подібне), ви можете об'єднати нумератори методом every_with_index або просто використовувати with_index:

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

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

Це те, що можна зробити з рубінів 1.8.7 та 1.9.


1
Варто зазначити, що це нове в 1.9.
Зак Ленглі

1
Добре помічений. Насправді це також у 1.8.7, але варто щось додати.
paradoja

чому я на Ruby 1.8.6, якщо я щойно встановив всю річ на Ubuntu? 1.8.8 експериментально / бета-версія?
Дан Розенстарк

Який Ubuntu ви використовуєте? У Intrepid є 1.8.7. Це остання стабільна версія ( ruby-lang.org/en/downloads ). Тим не менш, можеш маніпулювати рубіном 1.8.6 з такою ж поведінкою (див. Строго- неналежно.com/8/09/ruby-187s-enumerator-class.html ).
paradoja

3
Я втомився від відставання дистрибутива, тому я почав використовувати rvm для управління моєю установкою Ruby на Ubuntu та Linux Mint.
Бляшаний чоловік

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

Ви не можете зробити це за допомогою. Мені зазвичай подобається більш декларативний дзвінок кожному особисто. Частково тому, що його легко перейти в інші форми, коли ви досягаєте межі синтаксису.


Приємно, я бачу сенс щодо обмежень із синтаксисом for. Мені доводиться звикати до блоків з кількома параметрами.
Дан Розенстарк

11

Так, це 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}

Без проблем, рада допомогти. Не означав бути "середнім" щодо блоку .each - це основні рубінові конструкції, і навчити їх на льоту буде дуже, дуже болісно. :) Найкраще кусати кулю і провести кілька годин за читанням!
Метт Рогіш

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. Ви можете прочитати про це на сайті ruby-doc.org/core/classes/String.html#M000770 . Або ви можете набрати ri String #% у командному рядку. Або ви можете набрати ri%, щоб побачити всі задокументовані класи, які його розпізнають, наприклад, більш звичне значення у ri Fixnum #%.
Джордж

4

Що стосується вашого питання про те i++, що робити , ну, ви не можете цього зробити в Ruby. i += 1Заява потрібно було саме те, як ви повинні це зробити.



1

Якщо blahsце клас, який поєднується з Inumerable, ви повинні зробити це:

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

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.