Intenté traducir el siguiente código de Python a Go
import random
list = [i for i in range(1, 25)]
random.shuffle(list)
print(list)
pero encontré mi versión de Go larga e incómoda porque no hay función de reproducción aleatoria y tuve que implementar interfaces y convertir tipos.
¿Cuál sería una versión idiomática de Go de mi código?
Respuestas:
Como su lista es solo los números enteros del 1 al 25, puede usar Perm :
list := rand.Perm(25) for i, _ := range list { list[i]++ }
Tenga en cuenta que usar una permutación dada por
rand.Perm
es una forma efectiva de mezclar cualquier arreglo.dest := make([]int, len(src)) perm := rand.Perm(len(src)) for i, v := range perm { dest[v] = src[i] }
fuente
La respuesta de dystroy es perfectamente razonable, pero también es posible mezclar sin asignar cortes adicionales.
for i := range slice { j := rand.Intn(i + 1) slice[i], slice[j] = slice[j], slice[i] }
Consulte este artículo de Wikipedia para obtener más detalles sobre el algoritmo.
rand.Perm
en realidad también utiliza este algoritmo internamente.fuente
i!=j
cheque?Desde 1.10 Go incluye una función de reproducción aleatoria oficial de Fisher-Yates .
Documentación:
pkg/math/rand/#Shuffle
Vea también el original CL 51891
En primer lugar, como se ha comentado por shelll :
Ejemplo:
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)
fuente
rand.Seed(time.Now().UnixNano())
.La respuesta de Evan Shaw tiene un error menor. Si iteramos a través del segmento desde el índice más bajo al más alto, para obtener una mezcla aleatoria uniforme (pseudo) aleatoria, de acuerdo con el mismo artículo , debemos elegir un número entero aleatorio del intervalo
[i,n)
en lugar de[0,n+1)
.Esa implementación hará lo que necesita para entradas más grandes, pero para cortes más pequeños, realizará una mezcla no uniforme.
Para utilizar
rand.Intn()
, podemos hacer:for i := len(slice) - 1; i > 0; i-- { j := rand.Intn(i + 1) slice[i], slice[j] = slice[j], slice[i] }
siguiendo el mismo algoritmo del artículo de Wikipedia.
fuente
Quizás también puedas usar la siguiente función:
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] } }
fuente
Cuando use el
math/rand
paquete, no olvide establecer una fuente// 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.
Entonces escribí una
Shuffle
función que toma esto en consideración: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] } }
Y para usarlo:
source := rand.NewSource(time.Now().UnixNano()) array := []interface{}{"a", "b", "c"} Shuffle(array, source) // [c b a]
Si desea utilizarlo, puede encontrarlo aquí https://github.com/shomali11/util
fuente
El enfoque de Raed es muy inflexible debido a su
[]interface{}
entrada. Aquí hay una versión más conveniente para 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) } }
Uso de ejemplo:
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]
Y además, no olvides que un poco de copia es mejor que un poco de dependencia.
fuente
Utilice Shuffle () de la
math/rand
biblioteca.He aquí un ejemplo:
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) }
Dado que proviene de la
math/rand
biblioteca, es necesario sembrar. Consulte aquí para obtener más detalles.fuente