Ruby-配列を比較し、条件に基づいてインデックスを取得します
私は2つの配列を持っています
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
ただし、valは設定されません。
回答
1つは書くことができます
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
Array#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
配列、セット、およびハッシュの速度比較の詳細(ベンチマークを使用):Rubyでのセットの利点
私が思いつくことができる最もパフォーマンスの高いソリューションは次のとおりです。
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
はでありSet、ではないことに注意してくださいArray。配列をセットに変換することは理にかなっていますfind_last_index
が、同じセットで何度も呼び出す場合に限ります。そうしないと、配列をセット(to_set
)に変換するプロセスに、のSet#include?
代わりにを使用して得られるよりも多くの時間がかかりますArray#include?
。したがって、find_last_index
1回だけ使用する場合は、を呼び出すの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
その後は「3」になりました。val
その後、実際に検査しましたか?
p val
?これが私のトランスクリプトのスクリーンショットです。