检查两个数组是否具有相同的内容(以任何顺序)

我在Rails 1.2.3中使用了Ruby 1.8.6,并且需要确定两个数组是否具有相同的元素,而不pipe它们是否以相同的顺序排列。 其中一个数组保证不包含重复项(另一个可能,在这种情况下答案是否定的)。

我的第一个想法是

require 'set' a.to_set == b.to_set 

但是我想知道是否有更高效或习惯的做法。

这不需要转换来设置:

 a.sort == b.sort 

对于两个数组A和B:A和B具有相同的内容如果: (AB).blank? and (BA).blank? (AB).blank? and (BA).blank?

或者你可以检查: ((AB) + (BA)).blank?

同样如@ cort3z所示,这个解决schemeals0适用于多态数组,即

  A = [1 , "string", [1,2,3]] B = [[1,2,3] , "string", 1] (AB).blank? and (BA).blank? => true # while A.uniq.sort == B.uniq.sort will throw error `ArgumentError: comparison of Fixnum with String failed` 

:::::::::::编辑:::::::::::::

正如在评论中所build议的,上面的解决scheme失败的重复。虽然根据甚至没有要求的问题,因为提问者不是重复的兴趣(他正在转换他的数组设置之前检查,并且面具重复,即使你看在检查之前,他正在使用.uniq运算符,并且掩盖重复。)。 但是,如果重复您感兴趣,只要添加一个计数检查将修复相同(根据问题只有一个数组可以包含重复)。 所以最终的解决scheme是: A.size == B.size and ((AB) + (BA)).blank?

ab的元素是Comparable

 a.sort == b.sort 

@ mori的回答基于@ steenslag的评论的更正

如果您期望[:a, :b] != [:a, :a, :b] to_set不起作用。 您可以改用频率:

 class Array def frequency p = Hash.new(0) each{ |v| p[v] += 1 } p end end [:a, :b].frequency == [:a, :a, :b].frequency #=> false [:a, :b].frequency == [:b, :a].frequency #=> true 

速度比较

 require 'benchmark/ips' require 'set' a = [1, 2, 3, 4, 5, 6] b = [1, 2, 3, 4, 5, 6] Benchmark.ips do |x| x.report('sort') { a.sort == b.sort } x.report('sort!') { a.sort! == b.sort! } x.report('to_set') { a.to_set == b.to_set } x.report('minus') { ((a - b) + (b - a)).empty? } end Warming up -------------------------------------- sort 88.338ki/100ms sort! 118.207ki/100ms to_set 19.339ki/100ms minus 67.971ki/100ms Calculating ------------------------------------- sort 1.062M (± 0.9%) i/s - 5.389M in 5.075109s sort! 1.542M (± 1.2%) i/s - 7.802M in 5.061364s to_set 200.302k (± 2.1%) i/s - 1.006M in 5.022793s minus 783.106k (± 1.5%) i/s - 3.942M in 5.035311s 

如果你知道数组的长度是相等的,而且两个数组都不包含重复的数据,那么这种方式是很好的

 ( array1 & array2 ) == array1 

一种方法是迭代不重复的数组

 # assume array a has no duplicates and you want to compare to b !a.map { |n| b.include?(n) }.include?(false) 

这将返回一个trues数组。 如果出现任何错误,那么外面的include? 将返回true。 因此,你必须反转整个事情,以确定它是否匹配。