检查两个数组是否具有相同的内容(以任何顺序)
我在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?
当a
和b
的元素是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。 因此,你必须反转整个事情,以确定它是否匹配。