Ruby each_with_index offset


84

ฉันสามารถกำหนดออฟเซ็ตของดัชนีใน each_with_index loop iterator ได้หรือไม่ ความพยายามตรงไปตรงมาของฉันล้มเหลว:

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

แก้ไข:

คำชี้แจง: ฉันไม่ต้องการให้มีการชดเชยอาร์เรย์ฉันต้องการให้ดัชนีภายใน each_with_index ไม่ได้เริ่มจาก 0 แต่เช่น 1


คุณใช้ Ruby รุ่นอะไร?
fl00r

ขออภัยที่ไม่ได้เขียน แต่ฉันใช้ Ruby 1.9.2
Mark

คำตอบ:


110

อันที่จริงEnumerator#with_indexรับ offset เป็นพารามิเตอร์ทางเลือก:

[: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ไม่มี0
พารามิเตอร์

ที่จริงคำตอบที่สั้นกว่านั้นเป็นไปได้โปรดดูของฉันด้านล่าง
Zack Xu

50

ต่อไปนี้เป็นแบบรวบรัดโดยใช้คลาส Enumerator ของ Ruby

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

เอาท์พุท

1: foo
2: bar
3: baz

Array # แต่ละตัวส่งกลับตัวแจงนับและการเรียก 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 จริงเหรอ? ในตัวอย่างของฉันจะหยุดหลังจากสาม
sawa

แต่ถ้าออฟเซ็ตเป็น 2 หรือ 10 ล่ะ? ในกรณีของคุณชดเชยเป็นศูนย์ ฉันหมายความว่าที่นี่ไม่มีการชดเชยใด ๆ ใน (3)
fl00r ของคุณเมื่อ

@ fl00r คุณเพียงแค่เปลี่ยน+1ในรหัสของฉันไปหรือ+2 +10มันใช้งานได้เช่นกัน
sawa

OMG ผู้เขียนแก้ไขโพสต์ของเขาดังนั้นเขาจึงต้องการการชดเชยดัชนีไม่ใช่อาร์เรย์
fl00r


4

ฉันวิ่งเข้าไป

วิธีแก้ปัญหาของฉันไม่จำเป็นดีที่สุด แต่ก็ใช้ได้ผลสำหรับฉัน

ในการดูซ้ำ:

เพียงแค่เพิ่ม: ดัชนี + 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

นอกจากนี้ฉันควรสังเกตด้วยว่าหากออฟเซ็ตมากกว่าขนาด Array ของคุณมันจะเกิดข้อผิดพลาด เพราะ:

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

เท่าที่คุณอัปเดตคำถามของคุณและตอนนี้คุณไม่จำเป็นต้องใช้ Array offset แต่ Index offset ดังนั้นโซลูชัน @sawa จะทำงานได้ดีสำหรับคุณ


1

แอเรียลพูดถูก นี่เป็นวิธีที่ดีที่สุดในการจัดการเรื่องนี้และก็ไม่ได้แย่ขนาดนั้น

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

นั่นเป็นที่ยอมรับได้อย่างสมบูรณ์และดีกว่าวิธีแก้ปัญหาส่วนใหญ่ที่ฉันเคยเห็นในเรื่องนี้ ฉันคิดเสมอว่านี่คือสิ่งที่ # วัตถุมีไว้เพื่อ ...


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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.