2016-04-11 13 views
7

Ưu điểm chính của Set dường như là duy trì các yếu tố độc đáo. Nhưng điều đó có thể dễ dàng đạt được trong Array với,Ưu điểm của Thiết lập trong ruby ​​

array = [2,3,4] 
array | [2,5,6] # => [2,3,4,5,6] 

Các tính năng khác biệt duy nhất (có thể áp dụng cho vài trường hợp sử dụng) Tôi đã xem qua là,

set1 = [1,2,3].to_set 
set2 = [2,1,3].to_set 
set1 == set2 # => true 
[1,2,3] == [2,1,3] # => false 

Kể từ Array có chức năng khác nhau và hoạt động liên kết với nó, khi nào và tại sao tôi nên sử dụng Set?

Có nhiều liên kết so sánh ArraySet nhưng tôi chưa gặp phải ứng dụng quan trọng nào là Set.

+1

Đây là một câu hỏi rộng và được xác định rõ ràng bởi các ý kiến. Như bạn đã nói, tất cả phụ thuộc vào trường hợp sử dụng.Thực tế bạn đã tìm thấy vài trường hợp sử dụng cho các bộ không có nghĩa là điều này là như nhau cho tất cả. –

+0

Tôi mới lập trình và ruby. Khi tôi đề cập đến 'vài trường hợp sử dụng', tôi chỉ có nghĩa là thiếu sự tiếp xúc của tôi. Tôi đã hy vọng hiểu bộ và ứng dụng của nó tốt hơn bằng cách xem cách người khác đã triển khai (áp dụng) nó như thế nào. Cảm ơn. – Prashanth

+0

Tôi hiểu, Prashanth. Đừng tự mình lấy nó. Tôi chỉ có nghĩa rằng điều này là rất cá nhân và không thể được tổng quát một cách dễ dàng. –

Trả lời

8

Chắc chắn, bất cứ điều gì bạn có thể làm với Set, có cách để làm điều đó với Array. Lợi thế của việc sử dụng một Set là, vì nó được thực hiện dựa trên Hash, hầu hết các hoạt động trên nó là O (1) phức tạp, trong khi thực hiện nó với Array có thể là O (n).

Ví dụ:

Set.new([1, 2, 3]).include?(2) # O(1) complexity 
[1, 2, 3].include?(2) # O(n) complexity 
+0

Thật tuyệt vời khi có a) một liên kết bằng chứng và b) danh sách cụ thể hơn về các hoạt động “hầu hết”. – mudasobwa

1

Vâng, về mặt kỹ thuật bạn có thể đạt được kết quả tương tự sử dụng của Ruby ArraysSets. Nhưng, điều tương tự cũng có thể nói về Ruby ModulesClasses. Bạn có thể có các biến và phương thức trong cả hai, nhưng chúng phục vụ cho mục đích khác nhau và khi ai đó đọc mã, người đó sẽ nhận được ý nghĩa đó mà không cố gắng tìm ra các quyết định thiết kế của bạn.

Tôi đoán trường hợp của SetsArrays là giống nhau. Bạn có thể đạt được kết quả tương tự bằng cách sử dụng mảng, nhưng với các bộ biến của bạn truyền đạt thông tin bổ sung về logic nghiệp vụ của bạn (nội dung phải là duy nhất). Về cơ bản, chúng là các cấu trúc dữ liệu khác nhau. Có một lý do chúng tôi có cấu trúc dữ liệu khác nhau.

Thứ hai, với bộ mã của bạn là dễ đọc hơn, khi bạn làm các hoạt động như .subset?, .superset?, .intersect?, vv những người mới sẽ được đoán những gì array | array hoạt động thực hiện, nhưng với bộ đó là tất cả ở đó. Xem cái nào là dễ đọc hơn:

([1, 2, 3] & [2, 3]).empty?   # => false 
Set[1, 2, 3].intersect? Set[2, 3] # => true 

Thứ ba, các hoạt động giao với bộ là lẽ trước được tối ưu hóa và có thể chạy nhanh hơn.

5

Hai lớp học định nghĩa cấu trúc dữ liệu khác nhau:

Mảng

  • yếu tố có thể đã nhân đôi
  • duy trì lệnh
  • có thể được lặp để
  • tìm kiếm phần tử được chậm, phụ thêm yếu tố và nhận yếu tố từ vị trí nhanh chóng
  • duy trì duy nhất ess của các yếu tố là chậm

Sets

  • yếu tố không thể đã nhân đôi
  • không có đặt hàng (nền tảng lý thuyết: https://en.wikipedia.org/wiki/Partially_ordered_set)
  • tìm kiếm sự tồn tại của phần tử được nhanh chóng, phụ thêm phần tử là nhanh
  • tính độc đáo được đưa ra bởi thiết kế

Bộ đang thực sự lấy từ khái niệm toán học: https://en.wikipedia.org/wiki/Set_(mathematics)

Bên trong bên trong của Ruby thiết lập sử dụng băm cho việc lưu trữ, như đã nói trong tài liệu:

Set sử dụng Hash như lưu trữ, vì vậy bạn phải lưu ý những điểm sau đây:

Tính bình đẳng của các phần tử được xác định theo Object # eql? và Đối tượng # băm. Đặt giả định rằng danh tính của mỗi phần tử không thay đổi khi được lưu trữ. Sửa đổi phần tử của tập hợp sẽ hiển thị cài đặt thành trạng thái không đáng tin cậy. Khi một chuỗi được lưu trữ, một bản sao đông lạnh của chuỗi được lưu trữ thay vào đó, trừ khi chuỗi gốc đã bị đóng băng.

Khi bạn nhìn vào mã, nội bộ được lưu trữ dưới dạng băm với các đối tượng đã cho là khóa và boolean làm giá trị (chính xác: đúng khi đối tượng được thêm).

Tại sao người dùng nên sử dụng bộ? Nếu bạn muốn thực thi tính duy nhất và bạn không cần bất kỳ thứ tự - bộ nào là lựa chọn tốt nhất của bạn. Khi bạn không thực sự quan tâm đến tính độc đáo và thứ tự là quan trọng - Mảng là sự lựa chọn của bạn.

Nếu không - bạn cần phải quyết định arbitrally;)

3

Vì những lý do rõ ràng, nhìn thấy câu trả lời khác ở đây. Vì lý do performanse: xem kết quả của tiêu chuẩn này rất ít trong MRI của Ruby 1.9.3:

require 'benchmark' 
require 'set' 

array = (1..100000).to_a 
set = array.to_set 
#hash = Hash[array.map {|x| [x, nil]}] #beter voor heel grote volumes mar trager 
hash = Hash[*array] 

Benchmark.bmbm do |x| 
    x.report("Set.include?") { 10000.times { set.include?(99999) } } 
    x.report("Array.include?") { 10000.times { array.include?(99999) } } 
    x.report("Hash.include?") { 10000.times { hash.include?(99999) } } 
end 

Mà cho

Rehearsal -------------------------------------------------- 
Set.include?  0.000000 0.000000 0.000000 ( 0.015604) 
Array.include? 37.940000 0.000000 37.940000 (38.651992) 
Hash.include? 0.000000 0.000000 0.000000 ( 0.001000) 
---------------------------------------- total: 37.940000sec 

        user  system  total  real 
Set.include?  0.000000 0.000000 0.000000 ( 0.002001) 
Array.include? 38.157000 0.000000 38.157000 (38.730615) 
Hash.include? 0.000000 0.000000 0.000000 ( 0.001001) 

lý do đủ để sử dụng một Set hoặc Hash khi có thể.

Các vấn đề liên quan