2012-02-01 39 views
33

Tôi cần kiểm tra xem hai mảng có chứa cùng một dữ liệu theo bất kỳ thứ tự nào không. Sử dụng tưởng tượng compare phương pháp, tôi muốn làm:So sánh hai mảng trong Ruby

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 

tôi đã sử dụng arr1.sort == arr2.sort, xuất hiện để làm việc, nhưng là có một cách tốt hơn để làm điều này?

Trả lời

25

Sắp xếp các mảng trước khi so sánh chúng là O (n log n). Hơn nữa, như Victor chỉ ra, bạn sẽ gặp rắc rối nếu mảng chứa các đối tượng không thể sắp xếp. So sánh các biểu đồ, O (n) nhanh hơn.

Bạn sẽ tìm thấy Enumerable#frequency trong khía cạnh, nhưng thực hiện nó cho mình, mà là khá đơn giản, nếu bạn muốn tránh bổ sung thêm phụ thuộc:

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

Cảm ơn. Đây là giải pháp duy nhất trả về true cho 'arr1' và' arr2' đầu tiên, khi tôi so sánh từng mảng này: '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] '- Tôi không chắc liệu tôi sẽ luôn gặp rắc rối khi cài đặt đá quý, nhưng nếu tôi sử dụng nó cho một thứ gì đó, điều này có vẻ như phương pháp tốt hơn nhiều. – SimonMayer

+1

Bên cạnh n nhật ký n 'sắp xếp' không hoạt động tốt với các loại khác nhau, ví dụ: nếu có 'nil' s. Tần số nên làm việc tốt, ý tưởng tốt. –

+0

Việc thực hiện dễ dàng 'tần số' là bằng cách tiêm: lớp Array; tần số def; self.inject (Hash.new (0)) {| p, v | p [v] + = 1; p} kết thúc; Kết thúc –

3

Bạn thực sự có thể thực hiện phương pháp này bằng cách #comparemonkey patching lớp Array như thế này:

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

Hãy ghi nhớ rằng khỉ vá hiếm khi được coi là một thực hành tốt và bạn nên thận trọng khi sử dụng nó.

Có lẽ đó là cách tốt hơn để làm điều này, nhưng đó là những gì bạn nghĩ đến. Hy vọng nó giúp!

+1

Cảm ơn. Tôi biết tôi có thể làm điều đó. Tôi quan tâm hơn đến những gì 'so sánh' sẽ làm. – SimonMayer

+0

Thực ra đây là cách nhanh nhất, thậm chí so sánh với so sánh đã đặt ('Set.new (array1) == Set.new (mảng2)') –

29

Cách đơn giản nhất là sử dụng nút giao thông:

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

Vì vậy, báo cáo kết quả

@array2 & @array1 == @array2 

sẽ là true. Đây là giải pháp tốt nhất nếu bạn muốn kiểm tra xem array1 có chứa array2 hoặc ngược lại (điều đó khác). Bạn cũng không nghịch với mảng của bạn hoặc thay đổi thứ tự của các mục. Bạn cũng có thể so sánh độ dài của cả hai mảng nếu bạn muốn chúng giống nhau về kích thước.

Nó cũng là cách nhanh nhất để làm điều đó (chính xác cho tôi nếu tôi sai)

+8

Vì vậy, để có câu trả lời đầy đủ, 'a.size == b.size và a & b == a' được thực hiện như một phương thức' so sánh (a, b) 'hoặc một miếng vá khỉ. –

+0

'arr1 & arr3 == arr1' trả về true, mà tôi không muốn. Đề xuất của Mark là một cải tiến, nhưng đáng chú ý là nó không đối phó tốt với các giá trị trùng lặp. Xem ví dụ 'arr4 = [1,2,3,5,4,4]; p arr4.size == arr3.size và arr4 & arr3 == arr4', trả về true – SimonMayer

+0

@SimonMayer Tôi cầu xin sự khác biệt. 'arr3 = [3,4,2,1,5,5]; arr4 = [1,2,3,5,4,4]; p arr4 & arr3 == arr4' # => ** false ** –

12

Nếu bạn biết rằng không có lặp lại trong bất kỳ các mảng (ví dụ, tất cả các yếu tố này là duy nhất hoặc bạn don' t chăm sóc), sử dụng bộ là thẳng về phía trước và có thể đọc được:

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

đây là một phiên bản đó sẽ làm việc trên mảng unsortable

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) 
2

cách thanh lịch nhất mà tôi đã tìm thấy:

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 
+0

cũng hoạt động với các đối tượng –

+5

tôi được mã hóa như thế này trước, nhưng mã này có ngoại lệ nghiêm trọng. [1,1,1,1] - [1,2] = [], không giống nhau. – Canna

+0

đúng. cảm ơn vì đã chỉ ra điều này –

2

Bạn có thể mở lớp array và xác định phương thức như thế này.

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

arr1.compare(arr2) 
irb => true 

HOẶC sử dụng đơn giản

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

tôi đến trễ nhưng trong trường hợp này với ruby ​​2.3.x:

arr1 = [1,2,3,5,4] 
arr2 = [3,4,2,1,5] 
arr3 = [3,4,2,1,5,5] 

tôi sử dụng:

a - b == b - a && a.length == b.length 
=> true 

a - c == c - a && a.length == c.length 
=> false 

Khi tôi chỉ muốn so sánh hai mảng có cùng một nội dung , tôi sử dụng:

a - b == b - a 
=> true 

a - c == c - a 
=> true 

Xin lỗi cho tiếng Anh xấu của tôi!

+1

Không. Thử các mảng [1,2,2] và [1,1,2] –

+0

Cảm ơn! Tôi nhận ra câu trả lời của tôi là sai. – hoangdd