Получить произвольный ключ/элемент с карты
Я новичок в Go, и теперь я хочу получить произвольный элемент с карты; какой идиоматический способ сделать это? Я могу думать только о чем-то вроде этого:
func get_some_key(m map[int]int) int {
for k := range m {
return k
}
return 0
}
Причина, по которой я хочу, это то, что я использую карту для поддержки набора заданий, а с помощью карты я могу получить отложенное задание или удалить готовое задание в O (1). Я предполагаю, что это должно быть обычным требованием, но не очевидно, как это сделать в Go.
Ответы
Ответ 1
Вопрос о том, является ли получение произвольного ключа из хеш-таблицы общим требованием, может обсуждаться. В других реализациях языковых карт часто отсутствует эта функция (например, словарь в С#)
Тем не менее, ваше решение, вероятно, самое быстрое, но у вас останется псевдослучайный алгоритм, который вы не контролируете. И хотя текущая реализация использует псевдослучайный алгоритм, спецификация Go не дает никаких гарантий того, что она действительно будет случайной, а только то, что она не гарантированно предсказуема:
Порядок итераций для карт не указан и не гарантируется, что он будет одинаковым для каждой итерации.
Если вам нужен больший контроль над рандомизацией, вы также можете параллельно сохранить обновленный срез значений (или ключей), содержащихся в карте, используя выбранную вами рандомизацию (math/rand
или crypto/rand
для более экстремальных случаев), чтобы получить значение хранится в индексе, выбранном случайным образом, в срезе.
Ответ 2
Получение случайного ключа с карты просто включает в себя второй счетчик как случайное число.
// choices = map[string]...
i := rand.Intn(len(choices))
var k string
for k = range choices {
if i == 0 {
break
}
i--
}
fmt.Println(k, choices[k])
Карта может иметь любой тип действительного ключа, и вам просто нужно изменить var k string
для соответствия. Вы можете связать это как функцию:
func randIntMapKey(m map[int]string) int {
i := rand.Intn(len(m))
for k := range m {
if i == 0 {
return k
}
i--
}
panic("never")
}
Ответ 3
Вот более общая версия, хотя она может быть менее эффективной:
keys := reflect.ValueOf(mapI).MapKeys()
return keys[rand.Intn(len(keys))].Interface()
https://play.golang.org/p/0uvpJ0diG4e