Đặt cấu trúc dữ liệu trong Golang


69

Tôi thực sự thích google golang nhưng ai đó có thể giải thích lý do căn bản cho những người triển khai đã bỏ qua một cấu trúc dữ liệu cơ bản như các bộ từ thư viện chuẩn không?


8
Ngôn ngữ thực sự được gọi là Go, không phải golang
jozefg

92
Nhưng "golang" dễ tìm kiếm hơn
Matt

18
Cách tìm kiếm nhiều hơn. Googling "go set" trả về hình ảnh của một tấm gỗ với các mảnh màu đen và trắng.
Doug Richardson

Câu trả lời:


68

Một lý do tiềm năng cho sự thiếu sót này là việc mô hình hóa các bộ với bản đồ thực sự dễ dàng.

Thành thật mà nói tôi nghĩ đó là một chút quá sức, tuy nhiên nhìn vào Perl, câu chuyện hoàn toàn giống nhau. Trong Perl, bạn nhận được danh sách và hàm băm, trong Go bạn nhận được mảng, lát và bản đồ. Trong Perl, bạn thường sử dụng hàm băm cho bất kỳ và tất cả các vấn đề liên quan đến một bộ, điều tương tự cũng được áp dụng cho Go.

Thí dụ

để bắt chước một ints set trong Go, chúng tôi xác định bản đồ:

set := make(map[int]bool)

Để thêm một cái gì đó dễ dàng như:

i := valueToAdd()
set[i] = true

Xóa một cái gì đó chỉ là

delete(set, i)

Và sự vụng về tiềm năng của cấu trúc này dễ dàng bị trừu tượng hóa:

type IntSet struct {
    set map[int]bool
}

func (set *IntSet) Add(i int) bool {
    _, found := set.set[i]
    set.set[i] = true
    return !found   //False if it existed already
}

Và xóa và nhận có thể được định nghĩa tương tự, tôi có thực hiện đầy đủ ở đây . Sự bất mãn lớn ở đây là thực tế là đi không có thuốc generic. Tuy nhiên, có thể làm điều này với interface{}trường hợp bạn đã đưa ra kết quả nhận được.


3
Đây là phiên bản sửa đổi một chút của tôi với các phương thức Chứa và Kích thước: play.golang.org/p/tDdutH672-
Rick-777

19
Thay vì map[int]boolngười ta có thể sử dụng map[int]struct{}thay thế. Tôi thích cuối cùng.
pepper_chico

20
map[int]struct{}.. struct{}Mất 0 byte.
Boopathi Rajaa

2
github.com/fatih/set là một triển khai của tôi dựa trên bản đồ và các cấu trúc trống. Đó là chủ đề an toàn và có một api đơn giản.
Fatih Arslan

6
Với map[int]struct{}bạn không thể làm gì if mymap["key"] {để kiểm tra tư cách thành viên. Google khuyên bạn nên sử dụngbool (tìm kiếm "Có thể triển khai một bộ").
Timmmm

3

Tôi nghĩ rằng điều này phải làm với golangsự tập trung vào sự đơn giản. sets trở nên thực sự hữu ích với difference, intersection, union, issubset, và vân vân .. phương pháp. Có lẽ golangnhóm cảm thấy rằng nó là quá nhiều cho một cấu trúc dữ liệu. Nhưng mặt khác, một "tập câm" chỉ có add, containsremovecó thể dễ dàng nhân rộng với mapnhư được giải thích bởi @jozefg.


tôi không đồng ý. một bộ chủ yếu được sử dụng để kiểm tra thành viên và ngữ nghĩa đơn nhất. một cài đặt thực hiện sẽ hoàn toàn có thể sử dụng được nếu không có các phương thức đó. Điều đó đang được nói, họ cũng tầm thường để thực hiện.
Sedat Kapanoglu

2

Câu trả lời trước chỉ hoạt động NẾU khóa là loại tích hợp. Để bổ sung cho câu trả lời trước, đây là một cách để thực hiện một tập hợp có các thành phần là các loại do người dùng xác định:

package math

// types

type IntPoint struct {
    X, Y int
}

// set implementation for small number of items
type IntPointSet struct {
    slice []IntPoint 
}

// functions

func (p1 IntPoint) Equals(p2 IntPoint) bool {
    return (p1.X == p2.X) && (p1.Y == p2.Y)
}

func (set *IntPointSet) Add(p IntPoint) {
    if ! set.Contains(p) {
        set.slice = append(set.slice, p)
    }
}

func (set IntPointSet) Contains(p IntPoint) bool {
  for _, v := range set.slice {
    if v.Equals(p) {
      return true
    }
  }
  return false
}

func (set IntPointSet) NumElements() int {
    return len(set.slice)
}

func NewIntPointSet() IntPointSet {
  return IntPointSet{(make([]IntPoint, 0, 10))}
}

8
"CHỈ hoạt động NẾU khóa là loại tích hợp" là sai . type mySet map[IntPoint]boolhoạt động hoàn toàn tốt. Tất cả những gì được yêu cầu của loại khóa được sử dụng trong bản đồ là nó có ==!= . Bình đẳng của các loại cấu trúc được xác định rõ, Equalsphương pháp của bạn nên công bằng p1 == p2.
Dave C

1
Đúng là sự bình đẳng cho các cấu trúc được xác định rõ, nhưng nếu cấu trúc chứa bản đồ hoặc lát như các trường, chúng sẽ được so sánh bằng tham chiếu, thay vì theo giá trị. Đây có thể không phải là những gì bạn muốn.
Chaim-Leib Halbert

1
Tôi có một chút vấn đề với giải pháp này, bởi vì Containsmất thời gian tuyến tính, trong khi aMap[]mất thời gian không đổi, bất kể số lượng thành viên. Một giải pháp tốt hơn sẽ tạo ra một khóa duy nhất dựa trên nội dung của từng thành viên và tận dụng truy vấn thời gian liên tục mà maploại cung cấp. Ngay cả các giải pháp nhanh hơn xem xét hành vi bộ đệm, vv cũng tồn tại.
Chaim-Leib Halbert
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.