Tengo una array en la que elimino elementos random .
[a, b, c, d ,...] function getRandomItem(){ // return random item from array }También tengo una tabla SQL así:
category_id random_item Entonces quiero agregar ese elemento a la tabla. Para cada category_id , quiero varias filas de elementos aleatorios como:
category_id 1 y el category_id 2)Aquí hay un código imaginario que hace precisamente eso:
function persist(){ var a = giveRandomItem(); // $1 = a return execute("INSERT INTO mytable (random_item) values ($1) ON CONFLICT DO NOTHING RETURNING *", a) } // usage var persisted; while(persisted === undefined){ persisted = persist(); }El problema con esto es que no es un tiempo constante. Existe la probabilidad de que presione la base de datos 5 veces seguidas porque el elemento ya se ha conservado.
Para cada categoría, espero un máximo de 5k elementos y la longitud de mi matriz es de 400 000. Sin embargo, la probabilidad es bastante baja.
Sin embargo, me gustaría encontrar una forma que sea un tiempo constante, o al menos tener un comando sql que pruebe múltiples valores, para reducir aún más la probabilidad.
caso de uso
Un caso de uso simple que se me ocurre es este (es inútil pero simple):
A los usuarios se les presenta una interfaz donde pueden seleccionar una categoría. Luego pueden presionar un botón que le agrega un elemento aleatorio. Hay múltiples usuarios, cada uno actuando individualmente. Entonces, el usuario 1 puede agregar un elemento aleatorio a la categoría 1 mientras que el usuario 2 agrega simultáneamente un elemento aleatorio a la categoría 2
EDITAR
Terminé haciendo algo como esto:
A nivel de aplicación:
shuffle(array); function getRandomItem(seed, inc){ let index = (seed + inc) % array.length; return array[index] } // usage: let seed = item.category_id let inc = category.item_countDe esta manera, no tengo duplicados ya que dije que el recuento de elementos era menor que la longitud de la matriz. Además, los elementos son aparentemente aleatorios porque la identificación de la categoría se usa como semilla para el inicio del incremento. Sin embargo, eso es solo para el punto de partida y, por lo tanto, no es realmente aleatorio, pero funciona para mi caso de uso.
Para garantizar que no experimente conflictos (violaciones de restricciones únicas), debe cambiar su enfoque. En lugar de generar un elemento aleatorio a la vez, debe generar todos los elementos de 5K a la vez (y luego insertarlos en masa). La inserción a granel también aceleraría considerablemente las cosas.
¿Cómo generar elementos aleatorios de 5K a partir de una matriz de elementos de 400K?
Una forma es barajar la matriz y tomar los primeros 5K elementos. Luego los siguientes 5K elementos, y así sucesivamente. Esto también garantizaría que los lotes separados no tengan elementos repetitivos (hasta que se agoten los 400K y comience nuevamente desde el principio de la matriz).
Si desea que los elementos tengan la oportunidad de repetirse entre lotes, vuelva a mezclar la matriz entre los lotes.
Después de la discusión en los comentarios, parece que necesita un algoritmo que genere permutaciones cíclicas . Para cada categoría, almacene en la base de datos la semilla inicial/estado interno de este algoritmo para saber cómo continuar seleccionando elementos de una matriz de 400K de tal manera que parezcan aleatorios, pero no repita hasta que se seleccionen todos los elementos de 400K para la categoría.