golang tại sao chúng ta không có cơ sở hạ tầng được thiết lập [đóng]


129

Tôi đang cố gắng giải bài tập "Đường đi lập trình đi" # 1.4, yêu cầu tôi phải có một bộ. Tôi có thể tạo một loại tập hợp nhưng tại sao ngôn ngữ không đi kèm với một loại? đi, đến từ google, nơi ổi cũng bắt nguồn, tại sao các nhà thiết kế ngôn ngữ không chọn hỗ trợ cho các cấu trúc dữ liệu cơ bản? Tại sao buộc người dùng của bạn tạo các triển khai của riêng họ cho một cái gì đó cơ bản như một bộ?


11
hừm Tự hỏi tại sao các phiếu bầu tiêu cực? Tôi đến từ thế giới java nơi chúng tôi đã có một bộ gần như ngay từ đầu, ngay cả khi không có thuốc generic. Vì vậy, tôi thấy hành vi này thật kỳ quái
anjanb

Câu trả lời:


83

Một phần, bởi vì Go không có khái quát (vì vậy bạn sẽ cần một loại thiết lập cho mọi loại, hoặc phản ánh lại, điều này khá kém hiệu quả).

Một phần, bởi vì nếu tất cả những gì bạn cần là "thêm / xóa các phần tử riêng lẻ vào một tập hợp" và "tương đối hiệu quả về không gian", bạn có thể có được một chút công bằng chỉ bằng cách sử dụng một map[yourtype]bool(và đặt giá trị truecho bất kỳ phần tử nào trong tập hợp ) hoặc, để có hiệu quả không gian cao hơn, bạn có thể sử dụng một cấu trúc trống làm giá trị và sử dụng _, present = the_setoid[key]để kiểm tra sự hiện diện.


1
Ngoài ra, dường như theo tinh thần của Go là chỉ viết nó ra bằng mã của riêng bạn, bằng cách "nội tuyến" bộ trong mã khác hoặc xác định loại thiết lập của riêng bạn khi cần. Dù sao, việc sử dụng ví dụ std :: set <T> trong C ++ luôn xảy ra như là một phần của việc thực hiện chức năng hoặc thực hiện một số cấu trúc dữ liệu khác. Do đó, chỉ cần thực hiện cấu trúc dữ liệu khác trực tiếp bằng cách sử dụng bản đồ và lát và bất kỳ khối xây dựng nào khác mà bạn cần, nhưng không có bất kỳ bộ dựng sẵn nào. Mỗi lần sử dụng một bộ sẽ sử dụng nó một chút khác nhau :)
Bjarke Ebert

1
Nhưng thông thường, bạn không thực sự cần một bộ <Foo>, bạn sử dụng một bộ <Foo> như một phần của việc thực hiện một cái gì đó lớn hơn. Tôi đã thấy hàng tấn mã trong đó những điều bạn cần làm để bao gồm một thành phần "có thể tái sử dụng" tồi tệ hơn nhiều so với việc chỉ cần tránh. Vì vậy, ở đây chúng ta có một bộ <Foo>, chức năng ở đó cần một bộ <Bar>, ôi, chúng ta có hiệp phương sai chưa, hoặc làm thế nào để tạo một WrapperFactory để làm cho thứ này trông giống như thứ này, v.v. thực sự chỉ cần một giao diện có thể kiểm tra tư cách thành viên, vì vậy đừng gửi cho nó một bộ <Foo>.
Bjarke Ebert

42
Vậy nếu nó không có tướng, thì bản đồ 'chung' được triển khai như thế nào?
Fermin Silva

26
Lưu ý rằng nếu bạn muốn lưu byte, bạn có thể sử dụng map[T]struct{}thay vì map[T]bool.
nhấn chìm

4
Có một cái nhìn về emersion.fr/blog/2017/sets-in-go
emersion

69

Một lý do là dễ dàng tạo một bộ từ bản đồ:

s := map[int]bool{5: true, 2: true}
_, ok := s[6] // check for existence
s[8] = true // add element 
delete(s, 2) // remove element

liên hiệp

s_union := map[int]bool{}
for k, _ := range s1{
    s_union[k] = true
}
for k, _ := range s2{
    s_union[k] = true
}

Ngã tư

s_intersection := map[int]bool{}
for k,_ := range s1 { 
  if s2[k] {
    s_intersection[k] = true
  }
}

Nó không thực sự khó để thực hiện tất cả các hoạt động thiết lập khác.


10
Kiểm tra sự tồn tại chỉ đơn giản là lập chỉ mục bản đồ. Vì nếu không có trong đó, giá trị 0 (sẽ là false) sẽ cho biết điều đó. Không cần thành ngữ dấu phẩy-ok để thử nghiệm.
icza

2
Việc thực hiện cho giao lộ trông như thế cho sự khác biệt.
musiphil

1
@Kittsil cảm ơn bạn. Cập nhật.
Salvador Dali

34
Nó là tối ưu hơn để sử dụng map[int]struct{}thay vì bool, bởi vì một cấu trúc trống chiếm 0 byte trong bộ nhớ. Gần đây tôi đã viết một ý chính cho gist.github.com/bgadrian/cb8b9344d9c66571ef331a14eb7a2e80
BG Adrian

13
Điều đó không dễ dàng như vậy. Chỉ cần viết mã đó ở mọi nơi bạn cần để sử dụng Set có vẻ vô lý với tôi những ngày này. Hỗ trợ bộ sưu tập nên được cung cấp bởi bất kỳ ngôn ngữ. Hãy nghĩ một câu trả lời tốt hơn là Go vẫn chưa trưởng thành. Tôi chắc chắn sẽ có thư viện để trang trải điều đó sớm thôi.
Stef

5

Giống như Vatine đã viết: Vì đi thiếu khái quát, nó sẽ phải là một phần của ngôn ngữ chứ không phải là thư viện chuẩn. Vì vậy, sau đó bạn sẽ phải làm ô nhiễm ngôn ngữ với các từ khóa được đặt, liên kết, giao nhau, khác biệt, tập hợp con ...

Lý do khác là, nó không rõ ràng về việc thực hiện "quyền" của một bộ là gì:

  1. Có một cách tiếp cận chức năng:

    func IsInEvenNumbers(n int) bool {
        if n % 2 == 0 {
            return true
        }
       return false
    }

Đây là một tập hợp của tất cả các int thậm chí. Nó có một tra cứu và kết hợp rất hiệu quả, giao nhau, khác biệt và tập hợp con có thể dễ dàng được thực hiện bởi thành phần chức năng.

  1. Hoặc bạn làm một cách tiếp cận giống như Dali cho thấy.

Bản đồ không có vấn đề đó, vì bạn lưu trữ thứ gì đó liên quan đến giá trị.


2
Để xử lý các tập hợp buit-in, Pascal làm quá tải một nhóm toán tử nhị phân (hai đối số): +cho sự kết hợp, -cho sự khác biệt, *cho giao điểm, <=cho tập hợp con >=, =cho sự bình đẳng, <>cho sự bất bình đẳng và incho tư cách thành viên. Vì vậy, trong Go, nó sẽ chỉ là một từ khóa mới - in. Mặt khác, các bộ dựng sẵn của Pascal chỉ hoạt động trên "thứ tự" - nghĩa là, bất kỳ loại nào có biểu diễn cơ bản của một giá trị nguyên có kích thước nào đó.
kostix

9
Thực tế là có nhiều cách để thực hiện một tập hợp đã không ngăn được nhiều ngôn ngữ khác cung cấp chúng.
2/15

@kostix: Go thậm chí có thể sử dụng cú pháp s[key](như thể slà một map[T]bool) thay vì key in s.
musiphil

2
Bất kỳ lý do cho không chỉ đơn giản là trở về n % 2 == 0?
João Andrade

4

Một khả năng khác là sử dụng các tập bit, trong đó có ít nhất một gói hoặc bạn có thể sử dụng gói lớn tích hợp. Trong trường hợp này, về cơ bản, bạn cần xác định một cách để chuyển đổi đối tượng của mình thành một chỉ mục.


1
Tôi nên lưu ý rằng tôi đã viết phiên bản gốc của gói bitet được tham chiếu ở trên.
Will Fitzgerald
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.