ruby 检查两个数组是否具有相同的内容(以任何顺序)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10919783/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Check if two arrays have the same contents (in any order)
提问by Taymon
I'm using Ruby 1.8.6 with Rails 1.2.3, and need to determine whether two arrays have the same elements, regardless of whether or not they're in the same order. One of the arrays is guaranteed not to contain duplicates (the other might, in which case the answer is no).
我将 Ruby 1.8.6 与 Rails 1.2.3 一起使用,并且需要确定两个数组是否具有相同的元素,无论它们的顺序是否相同。保证其中一个数组不包含重复项(另一个可能,在这种情况下答案是否定的)。
My first thought was
我的第一个想法是
require 'set'
a.to_set == b.to_set
but I was wondering if there was a more efficient or idiomatic way of doing it.
但我想知道是否有更有效或更惯用的方法来做到这一点。
回答by Mori
This doesn't require conversion to set:
这不需要转换来设置:
a.sort == b.sort
回答by Sahil Dhankhar
for two arrays A and B:
A and B have same contents if:
(A-B).blank? and (B-A).blank?
对于两个数组 A 和 B: A 和 B 具有相同的内容,如果:
(A-B).blank? and (B-A).blank?
or you can just check for:
((A-B) + (B-A)).blank?
或者你可以只检查:
((A-B) + (B-A)).blank?
Also as suggested by @cort3z this solution als0 works for polymorphic arrays i.e
同样正如@cort3z 所建议的,这个解决方案 als0 适用于多态数组,即
A = [1 , "string", [1,2,3]]
B = [[1,2,3] , "string", 1]
(A-B).blank? and (B-A).blank? => true
# while A.uniq.sort == B.uniq.sort will throw error `ArgumentError: comparison of Fixnum with String failed`
::::::::::: EDIT :::::::::::::
::::::::::: 编辑 :::::::::::::
As suggested in the comments, above solution fails for duplicates.Although as per the question that is not even required since the asker is not interested in duplicates(he is converting his arrays to set before checking and that masks duplicates and even if you look at the accepeted answer he is using a .uniq operator before checking and that too masks duplicates.). But still if duplicates interests you ,Just adding a check of count will fix the same(as per the question only one array can contain duplicates). So the final solution will be:
A.size == B.size and ((A-B) + (B-A)).blank?
正如评论中所建议的那样,上述解决方案对于重复项失败。尽管根据甚至不需要的问题,因为提问者对重复项不感兴趣(他在检查之前将他的数组转换为 set 并且掩盖了重复项,即使你看他在检查之前使用 .uniq 运算符的公认答案也掩盖了重复项。)。但是,如果您对重复项感兴趣,只需添加一个计数检查即可解决相同的问题(根据问题,只有一个数组可以包含重复项)。所以最终的解决方案是:
A.size == B.size and ((A-B) + (B-A)).blank?
回答by Morozov
Speed comparsions
速度比较
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.338k i/100ms
sort! 118.207k i/100ms
to_set 19.339k i/100ms
minus 67.971k i/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
回答by Jared Beck
When the elements of aand bare Comparable,
当的元件a和b是Comparable,
a.sort == b.sort
Correction of @mori's answer based on @steenslag's comment
根据@steenslag 的评论更正@mori 的回答
回答by SRack
Ruby 2.6+
红宝石 2.6+
Ruby's introduced differencein 2.6.
Ruby 是difference在 2.6 中引入的。
This gives a very fast, very readable solution here, as follows:
这在这里提供了一个非常快速、非常易读的解决方案,如下所示:
a = [1, 2, 3, 4, 5, 6]
b = [1, 2, 3, 4, 5, 6]
a.difference(b).any?
# => false
a.difference(b.reverse).any?
# => false
a = [1, 2, 3, 4, 5, 6]
b = [1, 2, 3]
a.difference(b).any?
# => true
Running the benchmarks:
运行基准测试:
a = Array.new(1000) { rand(100) }
b = Array.new(1000) { rand(100) }
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? }
x.report('difference') { a.difference(b).any? }
end
sort 13.908k (± 2.6%) i/s - 69.513k in 5.001443s
sort! 14.656k (± 3.0%) i/s - 73.736k in 5.035744s
to_set 5.125k (± 2.9%) i/s - 26.023k in 5.082083s
minus 16.398k (± 2.2%) i/s - 83.181k in 5.074938s
difference 27.839k (± 5.2%) i/s - 141.048k in 5.080706s
Hope that helps someone!
希望对某人有所帮助!
回答by Victor Moroz
If you expect [:a, :b] != [:a, :a, :b]to_setdoesn't work. You can use frequency instead:
如果你期望[: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
回答by Nat
If you know the arrays are of equal length and neither array contains duplicates then this works too:
如果您知道数组的长度相等并且两个数组都不包含重复项,那么这也适用:
( array1 & array2 ) == array1
Explanation:the &operator in this case returns a copy of a1 sans any items not found in a2, which is the same as the original a1 iff both arrays have the same contents with no duplicates.
解释:&在这种情况下,运算符返回 a1 的副本,没有在 a2 中找到的任何项目,如果两个数组具有相同的内容且没有重复,则它与原始 a1 相同。
Analyis:Given that the order is unchanged, I'm guessing this is implemented as a double iteration so consistently O(n*n), notably worse for large arrays than a1.sort == a2.sortwhich should perform with worst-case O(n*logn).
Analyis:鉴于顺序没有改变,我猜这是作为一个双重迭代实现的,如此一致O(n*n),对于大数组来说尤其糟糕,而不是a1.sort == a2.sort在最坏情况下应该执行O(n*logn)。
回答by Ron
One approach is to iterate over the array with no duplicates
一种方法是在没有重复的情况下迭代数组
# assume array a has no duplicates and you want to compare to b
!a.map { |n| b.include?(n) }.include?(false)
This returns an array of trues. If any false appears, then the outer include?will return true. Thus you have to invert the whole thing to determine if it's a match.
这将返回一个真值数组。如果出现任何 false,则外部include?将返回 true。因此,您必须反转整个事物以确定它是否匹配。
回答by Todoroki
combining &and sizemay be fast too.
结合起来&也size可能很快。
require 'benchmark/ips'
require 'set'
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? }
x.report('&.size') { a.size == b.size && (a & b).size == a.size }
end
Calculating -------------------------------------
sort 896.094k (±11.4%) i/s - 4.458M in 5.056163s
sort! 1.237M (± 4.5%) i/s - 6.261M in 5.071796s
to_set 224.564k (± 6.3%) i/s - 1.132M in 5.064753s
minus 2.230M (± 7.0%) i/s - 11.171M in 5.038655s
&.size 2.829M (± 5.4%) i/s - 14.125M in 5.010414s

