Ruby - Bandingkan array dan dapatkan indeks berdasarkan kondisi
Saya memiliki dua array
array_input = %w[one two three two]
array_compare = %w[one two three four five]
Saya ingin mengekstrak indeks 'tertinggi' dari array_compare array, jika nilainya ada dalam array input. Keluaran yang diinginkan adalah 2
seperti yang three
ada dalam larik masukan dan compare
larik.
Saya sudah mencoba
val = nil
array_compare.reverse_each do |v|
val = v and break if array_input.include? v
end
tetapi tidak mengatur val.
Jawaban
Seseorang bisa menulis
array_compare.rindex { |e| array_input.include?(e) }
#=> 2
tetapi itu membutuhkan pencarian linier array_input
untuk setiap elemen array_compare
(dimulai dengan yang terakhir) hingga ditemukan kecocokan. Yang lebih baik adalah yang berikut ini.
array_compare.rindex((array_compare & array_input).last)
#=> 2
Langkah-langkahnya adalah sebagai berikut.
a = array_compare & array_input
#=> ["one", "two", "three"]
Lihat Array # & . Perhatikan bahwa "Urutan dipertahankan dari larik asli [ array_compare
].". Operasi sekali jalan ini akan sangat cepat karena diimplementasikan di C. Melanjutkan,
e = a.last
#=> "three"
array_compare.rindex(e)
#=> 2
Lihat Array # rindex .
Jika saya mengerti dengan benar,
ekstrak indeks 'tertinggi' dari array_compare array, jika nilainya ada di array input,
ini bisa menjadi pilihan:
array_compare.map.with_index { |e, id| id if array_input.include? e }.compact.max #=> 2
Jika array_compare = %w[one two three four five three]
, itu kembali 5
.
Ubah larik yang digunakan untuk pencarian menjadi satu set , untuk pencarian lebih cepat.
Iterasi dari akhir larik tempat Anda mencari indeks maks (seperti yang Anda lakukan dengan benar), juga untuk kecepatan. Solusi yang mengulang dari awal larik dan memilih indeks maks biasanya lebih lambat karena semua pencarian yang tidak berguna hingga elemen terakhir yang cocok ditemukan. Metode di bawah berhenti dengan cepat - pada pertandingan pertama yang berhasil.
Terakhir, perbaiki indeks maks, karena array_compare.reverse.each_with_index
mengembalikan indeks dari array terbalik .
Kode yang dihasilkan mungkin lebih panjang daripada di banyak jawaban lainnya, tetapi ini sederhana dan cepat:
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
LIHAT JUGA:
Array.include? relatif lambat. Selain itu, jika Anda hanya memerlukan hash untuk pencarian, pertimbangkan untuk menggunakan set:https://stackoverflow.com/a/411164/967621
Lebih lanjut tentang perbandingan kecepatan untuk array, set, dan hashes (dengan tolok ukur): Keuntungan Set di ruby
Solusi paling berkinerja yang dapat saya hasilkan adalah:
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
Perhatikan bahwa argumennya set_input
adalah a Set, bukan Array. Mengonversi larik ke himpunan masuk akal, tetapi hanya jika Anda ingin memanggil find_last_index
berkali-kali dengan himpunan yang sama. Jika tidak proses konversi array untuk satu set ( to_set
) membutuhkan lebih banyak waktu, dari yang Anda dapat memperoleh menggunakan Set#include?
bukan sebuah Array#include?
. Jadi jika Anda hanya ingin menggunakan find_last_index
sekali, Anda tidak boleh memanggil find_last_index(array_input.to_set, array_compare)
, tetapi gunakan versi ini yang tidak menggunakan set sama sekali:
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
Anda mungkin ingin melihat tolok ukur solusi berbeda untuk masalah ini.
Saya baru saja mengeksekusi (menyalin & menempel) kode Anda di irb , dan val
"tiga" sesudahnya. Apakah Anda benar-benar memeriksanya val
setelah itu, yaitu
p val
? Ini adalah tangkapan layar transscript saya .