Встановлює структуру даних у Голангу


69

Мені дуже подобається google golang, але чи міг би хтось пояснити, яке обґрунтування полягає у тому, щоб реалізатори залишили базову структуру даних, таку як набори зі стандартної бібліотеки?


8
Мова насправді називається Іти, а не голанг
jozefg

92
Але "голанг" є більш пошуковим
Метт

18
Швидше шукати. Google "go set" повертає зображення дерев’яної дошки з чорно-білими шматочками.
Дуг Річардсон

Відповіді:


68

Однією з потенційних причин цього упущення є те, що моделювати набори з картою дуже просто.

Якщо чесно, я думаю, що це теж трохи недогляд, але, дивлячись на Perl, історія точно така ж. У Perl ви отримуєте списки та хештелі, у Go ви отримуєте масиви, фрагменти та карти. У Perl ви, як правило, використовуєте хештел для будь-яких проблем, пов’язаних із набором, те саме стосується Go.

Приклад

щоб наслідувати набір ints в Go, визначимо карту:

set := make(map[int]bool)

Додавати щось так просто, як:

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

Видалити щось просто

delete(set, i)

І потенційна незграбність цієї конструкції легко усунути:

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
}

І видалити і отримати Аналогічно можна визначити, у мене є повна реалізація тут . Основним розладом тут є той факт, що у Go не є дженерики. Однак це можливо зробити interface{}в тому випадку, коли б ви привели результати отримання.


3
Ось моя трохи переглянута версія із методами вмісту
Rick-777

19
Замість цього map[int]boolможна використовувати один map[int]struct{}. Я віддаю перевагу останньому.
pepper_chico

20
map[int]struct{}.. struct{}Займає 0 байт.
Boopathi Rajaa

2
github.com/fatih/set - це реалізація моїх даних на основі карт і порожніх структур. Це безпечна нитка і має просту верхівку.
Фатих Арслан

6
З цим map[int]struct{}ви не можете зробити if mymap["key"] {перевірку на членство. Google рекомендує використовуватиbool (пошук "Набір може бути реалізований").
Timmmm

3

Я думаю, що це стосується golangзосередженості на простоті. setи стати дуже корисним з difference, intersection, union, issubsetі так далі .. методи. Можливо, golangкоманда відчула, що це занадто багато для однієї структури даних. Але в іншому випадку "тупий набір", який є лише add, containsі removeйого можна легко повторити, mapяк пояснив @jozefg.


я не погоджуюсь. набір здебільшого використовується для перевірки членства та семантики унікальності. реалізація набору була б цілком корисною без цих методів. що, як говориться, вони також тривіальні для реалізації.
Седат Капаноглу

2

Попередня відповідь працює ТІЛЬКО, якщо ключ є вбудованим типом. Щоб доповнити попередню відповідь, ось спосіб реалізувати набір, елементи якого визначені користувачем типів:

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
"працює ТОЛЬКО, якщо ключ є вбудованим типом" неправильно . type mySet map[IntPoint]boolпрацює прекрасно. Все, що потрібно для типу ключа, який використовується на карті, - це те, що він має ==і!= . Рівність типів структур чітко визначена, ваш Equalsметод повинен бути справедливим p1 == p2.
Дейв C

1
Це правда, що рівність для структур чітко визначена, але якщо структура містить карти або фрагменти як поля, вони будуть порівнюватися за посиланням, а не за значенням. Це може бути не те, що ви хочете.
Хаїм-Лейб Хальберт

1
Я займаюся цим питанням, оскільки це Containsзаймає лінійний час, а aMap[]постійний час, незалежно від кількості членів. Кращим рішенням буде внутрішньо створити унікальний ключ, що базується на вмісті кожного члена, та використовувати запити постійного часу, які mapнадає тип. Існують навіть більш швидкі рішення, що враховують поведінку кешу тощо.
Хаїм-Лейб Хальберт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.