比较Ruby中忽略元素顺序的两个数组

比较Ruby中忽略元素顺序的两个数组,ruby,arrays,comparison,Ruby,Arrays,Comparison,我需要检查两个数组是否以任何顺序包含相同的数据。 使用虚构的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,这似乎很有效,但有更好的方法吗?您可以通过如下数组类实际实现此#compare方法: class Array def comp

我需要检查两个数组是否以任何顺序包含相同的数据。 使用虚构的
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
,这似乎很有效,但有更好的方法吗?

您可以通过如下数组类实际实现此
#compare
方法:

class Array
  def compare(other)
    sort == other.sort
  end
end
请记住,猴子补丁很少被认为是一个好的做法,你应该谨慎使用它


也许有更好的方法可以做到这一点,但这正是我想到的。希望有帮助

在比较数组之前对它们进行排序是O(n logn)。此外,正如Victor所指出的,如果数组包含不可排序的对象,您将遇到麻烦。比较直方图的速度更快,O(n)

您可以在Facets中找到,但如果您希望避免添加更多依赖项,您可以自己实现它,这非常简单:

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
将为
。如果要检查
array1
是否包含
array2
或相反的内容(这是不同的),这是最好的解决方案。您也不会摆弄数组或更改项目的顺序。如果希望两个数组的大小相同,还可以比较它们的长度


这也是最快的方法(如果我错了,请纠正我)

如果您知道在任何数组中都没有重复(即,所有元素都是唯一的,或者您不在乎),那么使用集合是简单易懂的:

Set.new(array1) == Set.new(array2)

这是一个适用于不可排序数组的版本

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)

我发现的最优雅的方式是:

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

您可以打开
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]
arr2=[1,2,4]
arr1.差分(arr2)#=>[3]
arr2.差异(arr1)#=>[4]
#要检查数组是否相等,请执行以下操作:
arr2.差异(arr1).是否为空?
否则你可以用

# to check that arrays are equal:
arr1.sort == arr2.sort

谢谢我知道我能做到。我更关心的是
compare
将要做什么。实际上,这是最快的方法,甚至可以与set比较(
set.new(array1)==set.new(array2)
)进行比较。因此,对于完整的答案,
a.size==b.size和a&b==a
实现为
compare(a,b)
方法或猴子补丁。
arr1&arr3==arr1
返回true,这是我不想要的。马克的建议是一种改进,但值得注意的是,它不能很好地处理重复值。参见示例
arr4=[1,2,3,5,4,4];p arr4.size==arr3.size和arr4&arr3==arr4
,返回true@MarkThomas它在某些情况下有效,但并非所有情况下都有效。您能否获得适用于arr3和arr4的完整解决方案?我得到
arr3=[3,4,2,1,5,5];arr4=[1,2,3,5,4,4];p arr3.size==arr4.size和arr3&arr4==arr1#=>true
。应该是假的。不,不是<代码>a=[1,2,3,4,5,1];b=[1,1,2,3,4,5];(a.size==b.size)和&(a&b==a)
=>false
,但应为
true
,因为数组包含相同的项,只是顺序不同。如果允许数组包含重复的条目,union(
&
)解决方案将无法优雅地工作。此解决方案(即使使用大小检查)并非在所有情况下都能工作-应更新答案以澄清这一点,这样它就不会让人出错(请参见SimonMayer的[3,4,2,1,5,5]和[1,2,3,5,4]示例)。当我比较这些数组时,这是仅对第一个
arr1
arr2
返回true的唯一解决方案:
arr1=[1,2,3,5,4];arr2=[3,4,2,1,5];arr3=[3,4,2,1,5,5];arr4=[1,2,3,5,4,4]
-我不确定是否总是要麻烦地安装facets gem,但是如果我用它做某事,这似乎是一个更好的方法。此外,n log n
sort
不能很好地处理不同的类型,例如,如果存在
nil
s。频率应该可以正常工作,这是一个好主意。“频率”的一个简单实现是使用注入:类数组;def频率;self.inject(Hash.new(0)){p,v|p[v]+=1;p}end;endRuby 2.7的等价物将是
arr1.tally
=
arr2.tally
我第一次这样编码,但这段代码有一个严重的异常。[1,1,1,1]-[1,2]=[],这是不同的。