Imposta la struttura dei dati in Golang


69

Mi piace molto Google Golang, ma qualcuno potrebbe spiegare qual è la logica per gli implementatori che hanno lasciato fuori una struttura di dati di base come set dalla libreria standard?


8
La lingua in realtà si chiama Go, non Golang
jozefg

92
Ma "Golang" è più ricercabile
Matt

18
Molto più ricercabile. "Go set" di Google restituisce le immagini di una tavola di legno con pezzi in bianco e nero.
Doug Richardson,

Risposte:


68

Una potenziale ragione di questa omissione è che è davvero facile modellare i set con una mappa.

Ad essere sincero, penso che sia anche un po 'una svista, tuttavia guardando Perl, la storia è esattamente la stessa. In Perl ottieni elenchi e hashtabili, in Vai ottieni matrici, sezioni e mappe. In Perl useresti generalmente una tabella hash per tutti i problemi relativi a un set, lo stesso vale per Go.

Esempio

per imitare un set in Go, definiamo una mappa:

set := make(map[int]bool)

Aggiungere qualcosa è facile come:

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

Eliminare qualcosa è giusto

delete(set, i)

E il potenziale imbarazzo di questo costrutto viene facilmente sottratto:

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
}

E cancellare e ottenere può essere definito in modo simile, ho l'implementazione completa qui . Lo svantaggio principale qui è il fatto che andare non ha generici. Tuttavia è possibile farlo con interface{}nel qual caso avresti lanciato i risultati di get.


3
Ecco la mia versione leggermente rivista con i metodi Contains e Size: play.golang.org/p/tDdutH672-
Rick-777,

19
Invece di map[int]booluno può usare map[int]struct{}invece. Preferisco l'ultimo.
pepper_chico,

20
map[int]struct{}.. Il struct{}prende 0 byte.
Boopathi Rajaa,

2
github.com/fatih/set è un'implementazione della mia basata su mappe e strutture vuote. È thread-safe e ha una semplice API.
Fatih Arslan,

6
Con map[int]struct{}te non puoi fare if mymap["key"] {per verificare l'appartenenza. Google consiglia di utilizzarebool (cercare "È possibile implementare un set").
Timmmm,

3

Penso che questo abbia a che fare con l' golangattenzione sulla semplicità. sets diventare veramente utile con difference, intersection, union, issubset, e così via .. metodi. Forse il golangteam ha ritenuto che fosse troppo per una struttura di dati. Ma altrimenti un "set dumb" che ha solo add, containse removepuò essere facilmente replicato con mapcome spiegato da @jozefg.


non sono d'accordo. un set viene utilizzato principalmente per i controlli di appartenenza e la semantica di unicità. un'implementazione prestabilita sarebbe perfettamente utilizzabile senza questi metodi. detto questo, sono anche banali da implementare.
Sedat Kapanoglu,

2

La risposta precedente funziona SOLO SE la chiave è di tipo incorporato. Per completare la risposta precedente, ecco un modo per implementare un set i cui elementi sono tipi definiti dall'utente:

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
"funziona SOLO SE la chiave è di tipo incorporato" è errata . type mySet map[IntPoint]boolfunziona perfettamente. Tutto ciò che è richiesto per il tipo di chiave utilizzato in una mappa è che ha ==e!= . L'uguaglianza dei tipi di struttura è ben definita, il Equalsmetodo dovrebbe essere giusto p1 == p2.
Dave C,

1
È vero che l'uguaglianza per le strutture è ben definita, ma se la struttura contiene mappe o sezioni come campi, verranno confrontate per riferimento, piuttosto che per valore. Questo potrebbe non essere quello che vuoi.
Chaim-Leib Halbert,

1
Prendo un po 'di problemi con questa soluzione, perché Containsrichiede tempo lineare, mentre aMap[]richiede tempo costante, indipendentemente dal numero di membri. Una soluzione migliore creerebbe internamente una chiave univoca basata sul contenuto di ciascun membro e sfrutterà le query a tempo costante mapfornite dal tipo. Esistono anche soluzioni più veloci che considerano il comportamento della cache, ecc.
Chaim-Leib Halbert,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.