Ruby each_with_index offset - PullRequest
       37

Ruby each_with_index offset

80 голосов
/ 13 апреля 2011

Можно ли определить смещение индекса в итераторе цикла each_with_index? Моя прямая попытка не удалась:

some_array.each_with_index{|item, index = 1| some_func(item, index) }

Edit:

Уточнение: я не хочу смещения массива. Я хочу, чтобы индекс в each_with_index начинался не с 0, а, например, 1.

Ответы [ 10 ]

107 голосов
/ 13 апреля 2011

На самом деле, Enumerator#with_index получает смещение в качестве необязательного параметра:

[:foo, :bar, :baz].to_enum.with_index(1).each do |elem, i|
  puts "#{i}: #{elem}"
end

выходы:

1: foo
2: bar
3: baz

Кстати, я думаю, что это есть только в 1.9.2.

47 голосов
/ 24 октября 2013

Ниже приведено краткое описание с использованием класса перечислителя Ruby.

[:foo, :bar, :baz].each.with_index(1) do |elem, i|
    puts "#{i}: #{elem}"
end

output

1: foo
2: bar
3: baz

Каждый массив Array # возвращает перечислитель, а вызов Enumerator # with_index возвращает другого перечислителя, которомублок пройден.

5 голосов
/ 13 апреля 2011

1) Самое простое - заменить index+1 вместо index на функцию:

some_array.each_with_index{|item, index| some_func(item, index+1)}

но, вероятно, это не то, что вы хотите.

2) Следующее, что вы можете сделать, это определить другой индекс j внутри блока и использовать его вместо исходного индекса:

some_array.each_with_index{|item, i| j = i + 1; some_func(item, j)}

3) Если вы хотите так часто использовать индекс, определите другой метод:

module Enumerable
  def each_with_index_from_one *args, &pr
    each_with_index(*args){|obj, i| pr.call(obj, i+1)}
  end
end

%w(one two three).each_with_index_from_one{|w, i| puts "#{i}. #{w}"}
# =>
1. one
2. two
3. three


Обновление

Этот ответ, на который ответили несколько лет назад, теперь устарел. Для современных Рубинов ответ Зак Сюя будет работать лучше.

4 голосов
/ 03 октября 2011

Я столкнулся с этим.

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

В итерации представления:

просто добавьте: index+ 1

Это все для меня, так как я не использую никаких ссылок на эти номера индексов, но только для показа в списке.

4 голосов
/ 14 апреля 2011

Если some_index имеет какое-то значение, рассмотрите возможность использования хеша, а не массива.

3 голосов
/ 13 апреля 2011

Да, вы можете

some_array[offset..-1].each_with_index{|item, index| some_func(item, index) }
some_array[offset..-1].each_with_index{|item, index| some_func(item, index+offset) }
some_array[offset..-1].each_with_index{|item, index| index+=offset; some_func(item, index) }

UPD

Также я должен отметить, что если смещение больше, чем ваш размер массива, то это будет ошибкой.Потому что:

some_array[1000,-1] => nil
nil.each_with_index => Error 'undefined method `each_with_index' for nil:NilClass'

Что мы можем сделать здесь:

 (some_array[offset..-1]||[]).each_with_index{|item, index| some_func(item, index) }

Или для предварительной проверки смещения:

 offset = 1000
 some_array[offset..-1].each_with_index{|item, index| some_func(item, index) } if offset <= some_array.size

Это немного хаки

UPD 2

Насколько вы обновили свой вопрос и теперь вам нужно не смещение массива, а смещение индекса, чтобы решение @sawa работало для вас нормально

1 голос
/ 28 мая 2013

Это работает в каждой версии ruby:

%W(one two three).zip(1..3).each do |value, index|
  puts value, index
end

И для универсального массива:

a.zip(1..a.length.each do |value, index|
  puts value, index
end
1 голос
/ 22 октября 2012

Другой подход заключается в использовании map

some_array = [:foo, :bar, :baz]
some_array_plus_offset_index = some_array.each_with_index.map {|item, i| [item, i + 1]}
some_array_plus_offset_index.each{|item, offset_index| some_func(item, offset_index) }
1 голос
/ 19 октября 2012

Ариэль прав. Это лучший способ справиться с этим, и это не так уж плохо

ary.each_with_index do |a, i|
  puts i + 1
  #other code
end

Это вполне приемлемо и лучше, чем большинство решений, которые я видел для этого. Я всегда думал, что это было то, что #inject был для ... о хорошо.

0 голосов
/ 13 апреля 2011
offset = 2
some_array[offset..-1].each_with_index{|item, index| some_func(item, index+offset) }
...