Я не кажу, що Array
-> |value,index|
і Hash
-> |key,value|
не є божевільним (див. Коментар Горація Лоба), але я кажу, що є розумний спосіб очікувати такої домовленості.
Коли я маю справу з масивами, я зосереджений на елементах масиву (а не на індексі, тому що індекс є тимчасовим). Метод - кожен з індексом, тобто кожен + індекс, або | кожен, індекс |, або|value,index|
. Це також відповідає тому, що індекс розглядається як необов'язковий аргумент, наприклад, | value | еквівалентно | значення, індекс = нуль | що відповідає | значенню, індексу |.
Коли я маю справу з хешами, я часто більше зосереджуюся на ключах, ніж на значеннях, і я зазвичай маю справу з ключами та значеннями в тому порядку, key => value
або hash[key] = value
.
Якщо ви хочете набирати качок, то або явно використовуйте визначений метод, як показав Брент Лонгборо, або неявний метод, як показав maxhawkins.
Рубі полягає в тому, щоб пристосувати мову до програміста, а не про програміста, який відповідає мові. Ось чому існує так багато способів. Існує так багато способів думати про щось. У Ruby ви вибираєте найближчий, а решта коду зазвичай випадає надзвичайно акуратно та стисло.
Що стосується початкового запитання, "Який" правильний "спосіб пройти ітерацію через масив у Ruby?", Я думаю, що основним способом (тобто без потужного синтаксичного цукру чи об'єктно-орієнтованої сили) є:
for index in 0 ... array.size
puts "array[#{index}] = #{array[index].inspect}"
end
Але Ruby - це все сильний синтаксичний цукор та об'єктно-орієнтована потужність, але все одно тут еквівалент хешам, і ключі можна замовити чи ні:
for key in hash.keys.sort
puts "hash[#{key.inspect}] = #{hash[key].inspect}"
end
Отже, моя відповідь полягає в тому, що "правильний" шлях перегляду масиву в Ruby залежить від вас (тобто програміста або команди програмування) та проекту. " Кращий програміст Ruby робить кращий вибір (яка синтаксична сила та / або який об'єктно-орієнтований підхід). Кращий програміст Ruby продовжує шукати більше способів.
Тепер я хочу задати ще одне запитання: "Який" правильний "спосіб перебрати через Діапазон у Рубі назад?"! (Це питання, як я потрапив на цю сторінку.)
Приємно робити (для форвардів):
(1..10).each{|i| puts "i=#{i}" }
але мені не подобається це робити (для відсталих):
(1..10).to_a.reverse.each{|i| puts "i=#{i}" }
Ну, я насправді не проти робити це занадто багато, але коли я навчаю йти назад, я хочу показати своїм учням приємну симетрію (тобто з мінімальною різницею, наприклад, лише додавання реверсу або крок -1, але без модифікація будь-чого іншого). Можна зробити (для симетрії):
(a=*1..10).each{|i| puts "i=#{i}" }
і
(a=*1..10).reverse.each{|i| puts "i=#{i}" }
що мені не дуже подобається, але ви не можете цього зробити
(*1..10).each{|i| puts "i=#{i}" }
(*1..10).reverse.each{|i| puts "i=#{i}" }
#
(1..10).step(1){|i| puts "i=#{i}" }
(1..10).step(-1){|i| puts "i=#{i}" }
#
(1..10).each{|i| puts "i=#{i}" }
(10..1).each{|i| puts "i=#{i}" } # I don't want this though. It's dangerous
Ви могли в кінцевому рахунку зробити
class Range
def each_reverse(&block)
self.to_a.reverse.each(&block)
end
end
але я хочу навчити чистому Рубі, а не об'єктно-орієнтованим підходам (поки що). Я хотів би повторити:
- без створення масиву (врахуйте 0..1000000000)
- працює для будь-якого діапазону (наприклад, рядки, а не лише цілі числа)
- без використання додаткової об'єктно-орієнтованої потужності (тобто без модифікації класу)
Я вважаю, що це неможливо без визначення pred
методу, що означає модифікацію класу Range для його використання. Якщо ви можете це зробити, будь ласка, повідомте мене, інакше підтвердження неможливості буде вдячне, хоча це буде невтішно. Можливо, Ruby 1.9 вирішує це.
(Дякуємо за Ваш час на читання.)
array#each_with_index
використовує,|value, key|
тому що назва методу передбачає порядок, тоді як порядок, який використовується дляhash#each
імітаціїhash[key] = value
синтаксису?