Я не говорю, что Array
-> |value,index|
и Hash
-> |key,value|
не безумие (см. Комментарий Горация Лоеба), но я говорю, что есть разумный способ ожидать такой договоренности.
Когда я имею дело с массивами, я сосредотачиваюсь на элементах в массиве (а не на индексе, потому что индекс временный). Каждый метод имеет индекс, то есть каждый + индекс, или | каждый, индекс |, или |value,index|
. Это также согласуется с тем, что индекс рассматривается как необязательный аргумент, например | значение | эквивалентно | значение, index = nil | что согласуется с | значением, индексом |.
Когда я имею дело с хешами, я часто больше сосредотачиваюсь на ключах, чем на значениях, и обычно имею дело с ключами и значениями в этом порядке, key => value
или hash[key] = value
.
Если вам нужна утиная типизация, то либо явно используйте определенный метод, как показал Брент Лонгборо, либо неявный метод, как показал Максхокинс.
Ruby - это приспособление языка к программисту, а не приспособление программиста к языку. Вот почему существует так много способов. Есть так много способов думать о чем-то. В 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 продолжает искать новые пути.
Теперь я хочу задать другой вопрос: «Каков« правильный »способ перебрать Range в 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
но я хочу обучать чистому Ruby, а не объектно-ориентированным подходам (пока что). Я хотел бы повторить итерацию в обратном направлении:
- без создания массива (рассмотрим 0..1000000000)
- работает для любого диапазона (например, строки, а не только целые числа)
- без использования какой-либо дополнительной объектно-ориентированной мощности (т.е. без модификации класса)
Я считаю, что это невозможно без определения метода pred
, что означает изменение класса Range для его использования. Если вы можете это сделать, пожалуйста, дайте мне знать, в противном случае мы будем признательны за подтверждение невозможности, хотя оно будет разочаровывающим. Возможно, Ruby 1.9 решает эту проблему.
(Спасибо, что уделили время, чтобы прочитать это.)
person
Community
schedule
27.03.2009
array#each_with_index
использует|value, key|
, потому что имя метода подразумевает порядок, тогда как порядок, используемый дляhash#each
, имитирует синтаксисhash[key] = value
? - person Benjineer   schedule 12.05.2014