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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9095017/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 04:43:57  来源:igfitidea点击:

Comparing two arrays ignoring element order in Ruby

rubyarrayscomparison

提问by SimonMayer

I need to check whether two arrays contain the same data in any order. Using the imaginary comparemethod, I would like to do:

我需要检查两个数组是否以任何顺序包含相同的数据。使用虚构的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

I used arr1.sort == arr2.sort, which appears to work, but is there a better way of doing this?

我使用了arr1.sort == arr2.sort,这似乎有效,但有没有更好的方法来做到这一点?

采纳答案by tokland

Sorting the arrays prior to comparing them is O(n log n). Moreover, as Victor points out, you'll run into trouble if the array contains non-sortable objects. It's faster to compare histograms, O(n).

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

You'll find Enumerable#frequencyin Facets, but implement it yourself, which is pretty straightforward, if you prefer to avoid adding more dependencies:

您将在 Facets 中找到Enumerable#frequency,但如果您不想添加更多依赖项,则可以自己实现它,这非常简单:

require 'facets'
[1, 2, 1].frequency == [2, 1, 1].frequency 
#=> true

回答by MMM

The easiest way is to use intersections:

最简单的方法是使用交叉点:

@array1 = [1,2,3,4,5]
@array2 = [2,3,4,5,1]

So the statement

所以声明

@array2 & @array1 == @array2

Will be true. This is the best solution if you want to check whether array1contains array2or the opposite (that is different). You're also not fiddling with your arrays or changing the order of the items. You can also compare the length of both arrays if you want them to be identical in size.

true。如果您想检查是否array1包含array2或相反(即不同),这是最好的解决方案。您也不会摆弄数组或更改项目的顺序。如果您希望它们的大小相同,您还可以比较两个数组的长度。

It's also the fastest way to do it (correct me if I'm wrong)

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

回答by Gunchars

If you know that there are no repetitions in any of the arrays (i.e., all the elements are unique or you don't care), using sets is straight forward and readable:

如果您知道任何数组中都没有重复(即,所有元素都是唯一的或者您不在乎),则使用集合是直接且可读的:

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

回答by Tomislav Dyulgerov

You can actually implement this #comparemethod by monkey patchingthe Array class like this:

您实际上可以#compare通过像这样修补Array 类来实现此方法:

class Array
  def compare(other)
    sort == other.sort
  end
end

Keep in mind that monkey patching is rarely considered a good practice and you should be cautious when using it.

请记住,猴子补丁很少被认为是一种好的做法,在使用它时应谨慎。

There's probably is a better way to do this, but that's what came to mind. Hope it helps!

可能有更好的方法来做到这一点,但这就是我想到的。希望能帮助到你!

回答by Datt

You can open arrayclass and define a method like this.

您可以打开array类并定义这样的方法。

class Array
  def compare(comparate)
    to_set == comparate.to_set
  end
end

arr1.compare(arr2)
irb => true

OR use simply

或简单地使用

arr1.to_set == arr2.to_set
irb => true

回答by Lukasz Muzyka

The most elegant way I have found:

我发现的最优雅的方式:

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

回答by bmalets

Use difference method if length of arrays are the same https://ruby-doc.org/core-2.7.0/Array.html#method-i-difference

如果数组的长度相同,则使用差异方法 https://ruby-doc.org/core-2.7.0/Array.html#method-i-difference

arr1 = [1,2,3]
arr2 = [1,2,4]
arr1.difference(arr2) # => [3]
arr2.difference(arr1) # => [4]

# to check that arrays are equal:
arr2.difference(arr1).empty?

Otherwise you could use

否则你可以使用

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

回答by G. Allen Morris III

Here is a version that will work on unsortable arrays

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

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)