Ruby each_with_index 오프셋


84

each_with_index 루프 반복기에서 인덱스 오프셋을 정의 할 수 있습니까? 내 솔직한 시도는 실패했습니다.

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

편집하다:

설명 : 배열 오프셋을 원하지 않습니다. each_with_index 내의 인덱스가 0에서 시작하지 않고 예를 들어 1로 시작하기를 원합니다.


어떤 Ruby 버전을 사용하십니까?
fl00r 2011

글을 쓰지 않아서 미안하지만 Ruby 1.9.2를 사용합니다
Mark

답변:


110

실제로 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

BTW, 나는 1.9.2에만 있다고 생각합니다.


2
1.8.7에서는 없습니다 with_index더 PARAMS을에서 인덱스0
mpapis

실제로 더 짧은 답변이 가능합니다. 아래의 저를 참조하십시오.
Zack Xu

50

다음은 Ruby의 Enumerator 클래스를 사용하여 간결합니다.

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

산출

1: foo
2: bar
3: baz

Array # each는 열거자를 반환하고 Enumerator # with_index를 호출하면 블록이 전달되는 또 다른 열거자를 반환합니다.


5

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


최신 정보

몇 년 전에 답변 된이 답변은 이제 구식입니다. 현대 루비의 경우 Zack Xu의 답변이 더 잘 작동합니다.


배열에 더 이상 요소가 없어도 반복된다는 나쁜 점
fl00r

@ fl00r 정말? 내 예에서는 3시 후에 중지됩니다.
사와

그러나 오프셋이 2 또는 10이면? 귀하의 경우 오프셋은 0입니다. 내 말은 (3)에 오프셋이 없다는 뜻입니다
fl00r

@ fl00r +1내 코드에서 +2또는 +10. 그것도 작동합니다.
sawa 2011

OMG, 작성자가 자신의 게시물을 편집 했으므로 배열이 아닌 인덱스 오프셋이 필요합니다.
fl00r 2011

4

some_index의미가 있다면 배열보다는 해시를 사용하는 것이 좋습니다.


4

나는 그것을 만났다.

필요하지 않은 내 솔루션이 최고이지만 저에게 효과적이었습니다.

보기 반복에서 :

추가하기 : index + 1

그 색인 번호에 대한 참조를 사용하지 않고 목록에 표시하기 위해 사용하기 때문에 그게 전부입니다.


3

그래 넌 할수있어

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

아리엘이 맞습니다. 이것은 이것을 처리하는 가장 좋은 방법이며 그렇게 나쁘지는 않습니다.

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

그것은 완벽하게 수용 가능하며 내가 본 대부분의 솔루션보다 낫습니다. 나는 항상 이것이 #inject의 목적이라고 생각했습니다.


1

또 다른 접근 방식은 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

이것은 모든 루비 버전에서 작동합니다.

%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

두 번째 예에서 대괄호가 누락되었습니다.
Waferthin

0
offset = 2
some_array[offset..-1].each_with_index{|item, index| some_func(item, index+offset) }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.