与えられた:
a1 = [5, 1, 6, 14, 2, 8]
以下のすべての要素が含まれているかどうかを確認したいと思います。
a2 = [2, 6, 15]
この場合、結果はfalse
です。
そのような配列の包含を識別する組み込みのRuby/Railsメソッドはありますか?
これを実装する1つの方法は次のとおりです。
a2.index{ |x| !a1.include?(x) }.nil?
より良い、より読みやすい方法はありますか?
a = [5, 1, 6, 14, 2, 8]
b = [2, 6, 15]
a - b
=> [5, 1, 14, 8]
b - a
=> [15]
(b - a).empty?
=> false
おそらくこれは読みやすいです:
a2.all? { |e| a1.include?(e) }
配列交差を使用することもできます:
(a1 & a2).size == a1.size
ここではsize
が速度のためだけに使用されていることに注意してください。
(a1 & a2) == a1
しかし、最初の方が読みやすいと思います。これら3つは、プレーンRuby(Railsではありません)です。
これを行うことで達成できます
(a2 & a1) == a2
これにより、両方の配列の共通部分が作成され、a2
にあるa1
からすべての要素が返されます。結果がa2
と同じ場合、すべての要素がa1
に含まれていることを確認できます。
このアプローチは、最初にa2
のすべての要素が互いに異なる場合にのみ機能します。ダブルがある場合、このアプローチは失敗します。 Temposのものは今でも動作するので、私は心から彼のアプローチをお勧めします(また、おそらくより高速です)。
重複する要素がないか、それらを気にしない場合は、 Set クラスを使用できます。
a1 = Set.new [5, 1, 6, 14, 2, 8]
a2 = Set.new [2, 6, 15]
a1.subset?(a2)
=> false
これが使用する舞台裏
all? { |o| set.include?(o) }
Arrayクラスにモンキーパッチを適用できます。
class Array
def contains_all?(ary)
ary.uniq.all? { |x| count(x) >= ary.count(x) }
end
end
テスト
irb(main):131:0> %w[a b c c].contains_all? %w[a b c]
=> true
irb(main):132:0> %w[a b c c].contains_all? %w[a b c c]
=> true
irb(main):133:0> %w[a b c c].contains_all? %w[a b c c c]
=> false
irb(main):134:0> %w[a b c c].contains_all? %w[a]
=> true
irb(main):135:0> %w[a b c c].contains_all? %w[x]
=> false
irb(main):136:0> %w[a b c c].contains_all? %w[]
=> true
irb(main):137:0> %w[a b c d].contains_all? %w[d c h]
=> false
irb(main):138:0> %w[a b c d].contains_all? %w[d b c]
=> true
もちろん、メソッドは標準的なメソッドとして書くことができます。例えば
def contains_all?(a,b)
b.uniq.all? { |x| a.count(x) >= b.count(x) }
end
そして、あなたは次のように呼び出すことができます
contains_all?(%w[a b c c], %w[c c c])
実際、プロファイリング後、次のバージョンははるかに高速になり、コードは短くなります。
def contains_all?(a,b)
b.all? { |x| a.count(x) >= b.count(x) }
end
いずれかの配列に要素が重複している場合、(a1-a2)または(a1&a2)に基づくほとんどの回答は機能しません。私はここに到着し、Wordのすべての文字(配列に分割)が文字のセット(スクラブルなど)の一部であるかどうかを確認する方法を探しました。これらの答えはどれも機能しませんでしたが、これは機能します。
def contains_all?(a1, a2)
try = a1.chars.all? do |letter|
a1.count(letter) <= a2.count(letter)
end
return try
end
配列の大きさに応じて、効率的なアルゴリズムO(n log n)を検討できます。
def equal_a(a1, a2)
a1sorted = a1.sort
a2sorted = a2.sort
return false if a1.length != a2.length
0.upto(a1.length - 1) do
|i| return false if a1sorted[i] != a2sorted[i]
end
end
ソートコストO(n log n)と各ペアコストのチェックO(n)したがって、このアルゴリズムはO(n log n)です。他のアルゴリズムは、ソートされていない配列を使用して(漸近的に)高速化することはできません。