Mengatur Struktur Data di Golang

69

Saya sangat suka google golang tetapi dapatkah seseorang menjelaskan alasannya bagi para pelaksana karena tidak memiliki struktur data dasar seperti set dari pustaka standar?

cobie
sumber
8
Bahasa ini sebenarnya disebut Go, bukan golang
jozefg
92
Tetapi "golang" lebih mudah dicari
Matt
18
Jauh lebih mudah dicari. Googling "go set" mengembalikan gambar papan kayu dengan potongan hitam dan putih.
Doug Richardson

Jawaban:

68

Salah satu alasan potensial untuk penghilangan ini adalah sangat mudah untuk memodelkan set dengan peta.

Sejujurnya saya pikir itu agak terlalu kekeliruan, namun melihat Perl, ceritanya persis sama. Di Perl Anda mendapatkan daftar dan hashtable, di Go Anda mendapatkan array, irisan, dan peta. Di Perl, Anda biasanya menggunakan hashtable untuk setiap dan semua masalah yang berkaitan dengan set, hal yang sama berlaku untuk Go.

Contoh

untuk meniru set ints di Go, kami mendefinisikan peta:

set := make(map[int]bool)

Menambahkan sesuatu semudah:

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

Menghapus sesuatu itu adil

delete(set, i)

Dan potensi kecanggungan dari konstruksi ini dengan mudah disarikan:

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
}

Dan hapus dan dapatkan dapat didefinisikan dengan cara yang sama, saya memiliki implementasi lengkap di sini . Ketidaksukaan utama di sini adalah fakta bahwa tidak memiliki obat generik. Namun dimungkinkan untuk melakukan ini dengan interface{}dalam hal ini Anda akan mendapatkan hasil get.

jozefg
sumber
3
Inilah versi saya yang sedikit direvisi dengan metode Contains and Size: play.golang.org/p/tDdutH672-
Rick-777
19
Alih-alih map[int]boolsatu dapat menggunakan map[int]struct{}sebagai gantinya. Saya lebih suka yang terakhir.
pepper_chico
20
map[int]struct{}.. struct{}Dibutuhkan 0 byte.
Boopathi Rajaa
2
github.com/fatih/set adalah implementasi dari saya berdasarkan peta dan struct kosong. Threadnya aman dan memiliki api sederhana.
Fatih Arslan
6
Dengan map[int]struct{}Anda tidak dapat melakukan if mymap["key"] {untuk memeriksa keanggotaan. Google merekomendasikan penggunaanbool (mencari "Satu set dapat diimplementasikan").
Timmmm
3

Saya pikir ini ada hubungannya dengan golangfokus pada kesederhanaan. sets menjadi benar-benar berguna dengan difference, intersection, union, issubset, dan sebagainya .. metode. Mungkin golangtim merasa bahwa terlalu banyak untuk satu struktur data. Tetapi sebaliknya "set bodoh" yang hanya memiliki add, containsdan removedapat dengan mudah direplikasi dengan mapseperti yang dijelaskan oleh @jozefg.

Akavall
sumber
saya tidak setuju. satu set sebagian besar digunakan untuk cek keanggotaan dan semantik unik. implementasi yang ditetapkan akan sepenuhnya dapat digunakan tanpa metode-metode tersebut. itu dikatakan, mereka juga sepele untuk diterapkan.
Sedat Kapanoglu
2

Jawaban sebelumnya berfungsi HANYA JIKA kuncinya adalah tipe bawaan. Untuk melengkapi jawaban sebelumnya, berikut adalah cara untuk mengimplementasikan set yang elemen-elemennya adalah tipe yang ditentukan pengguna:

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))}
}
amahfouz
sumber
8
"berfungsi HANYA JIKA kuncinya adalah tipe bawaan" salah . type mySet map[IntPoint]boolbekerja dengan sangat baik. Semua yang diperlukan dari jenis kunci yang digunakan dalam peta adalah bahwa ia memiliki ==dan!= . Kesetaraan jenis struct didefinisikan dengan baik, Equalsmetode Anda harus adil p1 == p2.
Dave C
1
Memang benar bahwa kesetaraan untuk struct didefinisikan dengan baik, tetapi jika struct berisi peta atau potongan sebagai bidang, mereka akan dibandingkan dengan referensi, bukan oleh nilai. Ini mungkin bukan yang Anda inginkan.
Chaim-Leib Halbert
1
Saya mengambil sedikit masalah dengan solusi ini, karena Containsbutuh waktu linier, sementara aMap[]butuh waktu konstan, berapapun jumlah anggotanya. Solusi yang lebih baik akan secara internal membuat kunci unik berdasarkan konten masing-masing anggota, dan memanfaatkan kueri waktu-konstan yang mapdisediakan oleh tipe tersebut. Bahkan solusi yang lebih cepat yang mempertimbangkan perilaku cache, dll ada juga.
Chaim-Leib Halbert