¿Cómo seleccionarías un objeto aleatorio de una lista dada?

Aagh

Aaagh! Aagh !! Aaaaagh !!! Aaaaaaghgghh !!!! Aaaaaaghghghghgghhhhh !!!!!

De acuerdo, eso es suficiente. Cinco signos de exclamación !!!!! (Signo seguro de una mente loca [1])

La pregunta del título pide un objeto aleatorio , no (repito, no) un objeto pseudoaleatorio . Hay una gran diferencia: qué vergüenza si propusiste una solución que involucrara invocar algún tipo de función “rand ()” en el idioma que elijas.

Python: random () es pseudoaleatorio. C ++ rand () es pseudoaleatorio. Javascript Math.random () es pseudoaleatorio. Java Random y Math.random () son pseudoaleatorios. Todos estos son deterministas . No al azar XKCD hizo esto bien [2]:

Si quiere aleatorio, use / dev / random en una máquina Linux. Sin embargo, tenga en cuenta que esto se bloqueará cuando no haya suficiente entropía disponible. (Darwin [3] te ayuda en Windows).

De acuerdo, entiendo que el interrogador “realmente significaba un número pseudoaleatorio”, pero, muchachos, eso es realmente vergonzoso. La entropía verdadera es lo suficientemente difícil de adquirir sin que alguien la confunda con un generador de números pseudoaleatorios determinista, o simplemente sea intolerablemente descuidado.

Es este tipo de mierda lo que lleva a las personas a creer que los GUID de tipo 4 que obtienes de una caja de Windows tienen suficiente entropía para evitar colisiones. (Sugerencia: mira la entropía de la fuente).

Mi 2c, Jo.

[1] Múltiples signos de exclamación

[2] xkcd: número aleatorio

[3] O Dios, si ella existe. Estoy muy feliz de que Darwin existiera.

Estoy respondiendo en Java.

public E getRandom (List myList) {
Aleatorio r = nuevo Aleatorio ();
// descomenta si estás permitiendo modificaciones sincrónicas
// sincronizado (myList) {
return myList.get (r.getNextInt (myList.size () -1));
//}
}

Un par de cosas al respecto, al usar Random.getNextInt y el tamaño -1 de la Lista, he evitado tener que perder el tiempo con la preocupación de caerme al final de la matriz. Podría haber hecho lo mismo restringiendo el Aleatorio para que me devuelva un int una y otra vez hasta que devuelva uno menor que mi tamaño, use las matemáticas para hacer un número mayor que el 0 a 1 estándar u otros métodos (menciono esto Para luego). La técnica que use variará, pero sinceramente, creo que la mayoría de los idiomas admiten una construcción como la anterior.

En segundo lugar, bajo alta carga. SI esta lista se modifica simultáneamente, entonces necesitaría sincronizar alrededor de la línea de retorno como los comentarios anteriores, o usar una Lista concurrente (no es gran cosa de ninguna manera)

SI está en una carga de producción lo suficientemente alta como para sincronizar la lista, entonces puede hacer algo aún más interesante, que es obtener la longitud de la lista al comienzo de la función, y obtener el elemento como su último paso. Si la lista es escasa (no todos los elementos están poblados), entonces querrás usar un bloque while para seguir buscando según nuevos randoms hasta que encuentres uno, y nunca sincronizar. Si desea ver eso, déjeme un comentario y lo prepararé para usted.

Otra cosa que me siento obligado a mencionar es: ¿qué sucede si desea una solución en la que necesita sincronizar la lista, pero no puede permitirse sincronizarla? Esto presenta la SkipList, una lista de listas donde los elementos son escasos, pero numerados, y atravesar al final de una lista significa comenzar en la siguiente. usando una SkipList puede sincronizar una sublista, y no toda la lista principal, lo que puede evitar algunos de sus dolores de cabeza de sincronización.

Lista de saltos – Wikipedia

¡Buena suerte!

>>> lst = [“a”, “b”, “c”]
>>> importar al azar
>>> random.choice (lst)
‘C’

Uuuuh … OK, tal vez eso se considere hacer trampa (Python tiene la mayoría de estas preguntas de entrevista en su biblioteca estándar).

>>> lst [random.randint (0, len (lst) – 1)]
‘si’

¡¿Eso es mejor?! Quiero decir, en lo que respecta a las entrevistas; es horrible lo contrario.

Aun mejor”:

>>> lst [math.floor (random.random () * len (lst))]
‘una’

random devuelve un número que siempre es menor que 1, por lo que debería funcionar.

Si esto arroja excepciones de índice ilegales bajo carga, lo más probable es que sea un problema de subprocesamiento múltiple / sincronización: otro subproceso está modificando la lista entre obtener su longitud y acceder al elemento. La solución es poner alguna sincronización allí (por ejemplo, un mutex / bloqueo), o evitar datos mutables en general (si otro hilo quiere la lista, debe hacer una copia en lugar de usar la lista existente).