Я попытался перевести следующий код Python на Go
import random
list = [i for i in range(1, 25)]
random.shuffle(list)
print(list)
но моя версия Go показалась мне длинной и неудобной, потому что здесь нет функции перемешивания, и мне пришлось реализовать интерфейсы и преобразовать типы.
Какой была бы идиоматическая версия моего кода для Go?
Ответы:
Поскольку ваш список состоит только из целых чисел от 1 до 25, вы можете использовать Perm :
list := rand.Perm(25) for i, _ := range list { list[i]++ }
Обратите внимание, что использование перестановки, заданной параметром,
rand.Perm
является эффективным способом перемешивания любого массива.dest := make([]int, len(src)) perm := rand.Perm(len(src)) for i, v := range perm { dest[v] = src[i] }
источник
Ответ dystroy вполне разумен, но также можно перетасовать без выделения каких-либо дополнительных фрагментов.
for i := range slice { j := rand.Intn(i + 1) slice[i], slice[j] = slice[j], slice[i] }
См. Эту статью в Википедии для получения более подробной информации об алгоритме.
rand.Perm
фактически использует этот алгоритм и внутри.источник
i!=j
проверку?Начиная с версии 1.10 Go включает в себя официальную функцию перемешивания Fisher-Yates .
Документация:
pkg/math/rand/#Shuffle
См. Также оригинальный CL 51891
Прежде всего , как заметил по shelll :
Пример:
words := strings.Fields("ink runs from the corners of my mouth") rand.Shuffle(len(words), func(i, j int) { words[i], words[j] = words[j], words[i] }) fmt.Println(words)
источник
rand.Seed(time.Now().UnixNano())
.Ответ Эвана Шоу содержит небольшую ошибку. Если мы перебираем срез от наименьшего индекса к наибольшему, чтобы получить равномерно (псевдо) случайное перемешивание, согласно той же статье , мы должны выбрать случайное целое число от interval,
[i,n)
а не от[0,n+1)
.Эта реализация будет делать то, что вам нужно для больших входных данных, но для меньших фрагментов она будет выполнять неравномерное перемешивание.
Чтобы использовать
rand.Intn()
, мы можем:for i := len(slice) - 1; i > 0; i-- { j := rand.Intn(i + 1) slice[i], slice[j] = slice[j], slice[i] }
по тому же алгоритму из статьи в Википедии.
источник
Возможно, вы также можете использовать следующую функцию:
func main() { slice := []int{10, 12, 14, 16, 18, 20} Shuffle(slice) fmt.Println(slice) } func Shuffle(slice []int) { r := rand.New(rand.NewSource(time.Now().Unix())) for n := len(slice); n > 0; n-- { randIndex := r.Intn(n) slice[n-1], slice[randIndex] = slice[randIndex], slice[n-1] } }
источник
При использовании
math/rand
пакета не забудьте указать источник// Random numbers are generated by a Source. Top-level functions, such as // Float64 and Int, use a default shared Source that produces a deterministic // sequence of values each time a program is run. Use the Seed function to // initialize the default Source if different behavior is required for each run.
Поэтому я написал
Shuffle
функцию, которая учитывает это:import ( "math/rand" ) func Shuffle(array []interface{}, source rand.Source) { random := rand.New(source) for i := len(array) - 1; i > 0; i-- { j := random.Intn(i + 1) array[i], array[j] = array[j], array[i] } }
И использовать это:
source := rand.NewSource(time.Now().UnixNano()) array := []interface{}{"a", "b", "c"} Shuffle(array, source) // [c b a]
Если вы хотите его использовать, вы можете найти его здесь https://github.com/shomali11/util
источник
Подход Raed очень негибкий из-за
[]interface{}
входных данных. Вот более удобная версия для go> = 1.8 :func Shuffle(slice interface{}) { rv := reflect.ValueOf(slice) swap := reflect.Swapper(slice) length := rv.Len() for i := length - 1; i > 0; i-- { j := rand.Intn(i + 1) swap(i, j) } }
Пример использования:
rand.Seed(time.Now().UnixNano()) // do it once during app initialization s := []int{1, 2, 3, 4, 5} Shuffle(s) fmt.Println(s) // Example output: [4 3 2 1 5]
И также не забывайте, что небольшое копирование лучше, чем небольшая зависимость.
источник
Используйте Shuffle () из
math/rand
библиотеки.Вот пример:
package main import ( "fmt" "math/rand" "strings" ) func main() { words := strings.Fields("ink runs from the corners of my mouth") rand.Shuffle(len(words), func(i, j int) { words[i], words[j] = words[j], words[i] }) fmt.Println(words) }
Поскольку он поступает из
math/rand
библиотеки, его необходимо засеять. Подробнее см. Здесь .источник