Ruby - เปรียบเทียบอาร์เรย์และรับดัชนีตามเงื่อนไข
ฉันมีสองอาร์เรย์
array_input = %w[one two three two]
array_compare = %w[one two three four five]
ฉันต้องการแยกดัชนี 'สูงสุด' จากอาร์เรย์ array_compare หากมีค่าอยู่ในอาร์เรย์อินพุต เอาท์พุทที่ต้องการ2
เป็นthree
อยู่ในอาร์เรย์การป้อนข้อมูลและcompare
อาร์เรย์
ฉันพยายามแล้ว
val = nil
array_compare.reverse_each do |v|
val = v and break if array_input.include? v
end
แต่ไม่ได้ตั้งค่าวาล
คำตอบ
หนึ่งสามารถเขียน
array_compare.rindex { |e| array_input.include?(e) }
#=> 2
แต่ต้องใช้การค้นหาเชิงเส้นarray_input
สำหรับแต่ละองค์ประกอบของarray_compare
(เริ่มต้นด้วยสุดท้าย) จนกว่าจะพบรายการที่ตรงกัน ดีกว่าดังต่อไปนี้
array_compare.rindex((array_compare & array_input).last)
#=> 2
ขั้นตอนมีดังนี้
a = array_compare & array_input
#=> ["one", "two", "three"]
ดูArray # & . โปรดทราบว่า "ลำดับจะถูกเก็บรักษาไว้จากอาร์เรย์เดิม [ array_compare
]" การดำเนินการแบบครั้งเดียวนี้จะรวดเร็วมากเมื่อมีการใช้งานใน C.
e = a.last
#=> "three"
array_compare.rindex(e)
#=> 2
ดูอาร์เรย์ # rindex
ถ้าฉันเข้าใจถูกต้อง
แยกดัชนี 'สูงสุด' จากอาร์เรย์ array_compare หากค่ามีอยู่ในอาร์เรย์อินพุต
นี่อาจเป็นตัวเลือก:
array_compare.map.with_index { |e, id| id if array_input.include? e }.compact.max #=> 2
ถ้าarray_compare = %w[one two three four five three]
มันกลับ5
มา
แปลงอาร์เรย์ที่ใช้สำหรับการค้นหาเป็นชุดเพื่อให้ค้นหาได้เร็วขึ้น
วนซ้ำจากจุดสิ้นสุดของอาร์เรย์ที่คุณกำลังค้นหาดัชนีสูงสุด (ตามที่คุณกำลังทำอย่างถูกต้อง) และเพื่อความเร็ว โซลูชันที่วนซ้ำจากจุดเริ่มต้นของอาร์เรย์และเลือกดัชนีสูงสุดมักจะช้าลงเนื่องจากการค้นหาที่ไร้ประโยชน์ทั้งหมดจนกว่าจะพบองค์ประกอบที่ตรงกันล่าสุด วิธีการด้านล่างหยุดอย่างรวดเร็ว - ในการแข่งขันครั้งแรกที่ประสบความสำเร็จ
สุดท้ายแก้ไขดัชนีสูงสุดเนื่องจากarray_compare.reverse.each_with_index
ส่งคืนดัชนีของอาร์เรย์ที่กลับรายการ
รหัสผลลัพธ์อาจยาวกว่าในหลาย ๆ คำตอบ แต่ทั้งง่ายและรวดเร็ว:
require 'set'
array_input = %w[one two three two]
array_compare = %w[one two three four five]
set_input = array_input.to_set
i_max = nil
array_compare.reverse.each_with_index { |x, i| i_max = i and break if set_input.include? x }
# correct the index to count from the beginning of
# array_compare, not from the end:
i_max = array_compare.length - i_max - 1;
puts i_max; # prints: 2
ดูสิ่งนี้ด้วย:
Array.include? ค่อนข้างช้า นอกจากนี้หากคุณต้องการแฮชสำหรับการค้นหาเท่านั้นให้พิจารณาใช้ชุด:https://stackoverflow.com/a/411164/967621
ข้อมูลเพิ่มเติมเกี่ยวกับการเปรียบเทียบความเร็วสำหรับอาร์เรย์ชุดและแฮช (พร้อมเกณฑ์มาตรฐาน): ข้อดีของการตั้งค่าในทับทิม
วิธีแก้ปัญหาที่มีประสิทธิภาพมากที่สุดที่ฉันสามารถทำได้คือ:
def find_last_index(set_input, array_compare)
(array_compare.length - 1).downto(0) do |i|
return i if set_input.include?(array_compare[i])
end
end
โปรดทราบว่าอาร์กิวเมนต์set_input
คือ a Setไม่ใช่Array. การแปลงอาร์เรย์เป็นชุดนั้นเหมาะสม แต่ถ้าคุณต้องการเรียกfind_last_index
หลาย ๆ ครั้งด้วยชุดเดียวกัน มิฉะนั้นกระบวนการแปลงอาร์เรย์เป็น set ( to_set
) จะใช้เวลานานกว่าที่คุณจะได้รับโดยใช้ a Set#include?
แทนArray#include?
. ดังนั้นหากคุณต้องการใช้find_last_index
เพียงครั้งเดียวคุณไม่ควรโทรfind_last_index(array_input.to_set, array_compare)
แต่ใช้เวอร์ชันนี้ที่ไม่ใช้ชุดเลย:
def find_last_index(array_input, array_compare)
(array_compare.length - 1).downto(0) do |i|
return i if array_input.include?(array_compare[i])
end
end
คุณอาจต้องการดูเกณฑ์มาตรฐานของวิธีแก้ปัญหาต่างๆสำหรับปัญหานี้
ฉันเพิ่งดำเนินการ (คัดลอกและวาง) รหัสของคุณในirbและval
หลังจากนั้นเป็น "สาม" val
หลังจากนั้นคุณตรวจสอบจริงหรือไม่เช่น
p val
เหรอ? นี่คือภาพหน้าจอของ transscript