2つの配列に同じデータが任意の順序で含まれているかどうかを確認する必要があります。架空のcompare
メソッドを使用して、以下を実行します。
arr1 = [1,2,3,5,4]
arr2 = [3,4,2,1,5]
arr3 = [3,4,2,1,5,5]
arr1.compare(arr2) #true
arr1.compare(arr3) #false
arr1.sort == arr2.sort
を使用しましたが、動作しているようですが、これを行うより良い方法はありますか?
比較する前に配列を並べ替えるのはO(n log n)です。さらに、Victorが指摘しているように、配列にソート不可能なオブジェクトが含まれていると、問題が発生します。ヒストグラムO(n)を比較する方が高速です。
Facetsには Enumerable#frequency がありますが、依存関係の追加を避けたい場合は、ご自身で簡単に実装できます。
require 'facets'
[1, 2, 1].frequency == [2, 1, 1].frequency
#=> true
最も簡単な方法は、交差点を使用することです。
@array1 = [1,2,3,4,5]
@array2 = [2,3,4,5,1]
だから声明
@array2 & @array1 == @array2
true
になります。これは、array1
にarray2
が含まれているか、反対の(異なる)かを確認する場合に最適なソリューションです。また、配列をいじったり、項目の順序を変更したりすることもありません。また、サイズを同一にしたい場合は、両方の配列の長さを比較することもできます。
また、それを行うための最速の方法です(間違っている場合は修正してください)
どの配列にも繰り返しがないことがわかっている場合(つまり、すべての要素が一意であるか気にしないか)、セットの使用は簡単で読みやすいです:
Set.new(array1) == Set.new(array2)
実際にこれを実装できます#compare
メソッド monkey patching このようなArrayクラス:
class Array
def compare(other)
sort == other.sort
end
end
モンキーパッチングがグッドプラクティスと見なされることはめったにないので注意してください。
おそらくこれを行うためのより良い方法がありますが、それが思い浮かびました。それが役に立てば幸い!
array
クラスを開き、このようなメソッドを定義できます。
class Array
def compare(comparate)
to_set == comparate.to_set
end
end
arr1.compare(arr2)
irb => true
または単に使用する
arr1.to_set == arr2.to_set
irb => true
私が見つけた最もエレガントな方法:
arr1 = [1,2,3,5,4]
arr2 = [3,4,2,1,5]
arr3 = [3,4,2,1,5,5]
(arr1 - arr2).empty?
=> true
(arr3 - arr2).empty?
=> false
以下は、ソートできない配列で動作するバージョンです
class Array
def unordered_hash
unless @_compare_o && @_compare_o == hash
p = Hash.new(0)
each{ |v| p[v] += 1 }
@_compare_p = p.hash
@_compare_o = hash
end
@_compare_p
end
def compare(b)
unordered_hash == b.unordered_hash
end
end
a = [ 1, 2, 3, 2, nil ]
b = [ nil, 2, 1, 3, 2 ]
puts a.compare(b)