Подтвердить что ты не робот

Получить произвольный ключ/элемент с карты

Я новичок в Go, и теперь я хочу получить произвольный элемент с карты; какой идиоматический способ сделать это? Я могу думать только о чем-то вроде этого:

func get_some_key(m map[int]int) int {
    for k := range m {
        return k
    }
    return 0
}

Причина, по которой я хочу, это то, что я использую карту для поддержки набора заданий, а с помощью карты я могу получить отложенное задание или удалить готовое задание в O (1). Я предполагаю, что это должно быть обычным требованием, но не очевидно, как это сделать в Go.

4b9b3361

Ответ 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