Estoy trabajando para hacer coincidir un par de una lista de nombres en Apps Script, pero hay una condición adjunta que estoy tratando de resolver.
<table> <thead> <tr> <th>Names1</th> <th>Names2</th> </tr> </thead> <tbody> <tr> <td>Glen</td> <td>Adam</td> </tr> <tr> <td>John</td> <td>Matthew</td> </tr> <tr> <td>Mitch</td> <td>Damien</td> </tr> <tr> <td>Daryl</td> <td>Jason</td> </tr> <tr> <td>Steve</td> <td>Shane</td> </tr> <tr> <td>Ricky</td> <td>Stuart</td> </tr> </tbody> </table>Aquí está el enlace de las hojas de Google que explica la entrada y la salida esperada: https://docs.google.com/spreadsheets/d/1nwu5j2ae_NQAmNQ5WlC-etd12lYMr4FDNKt3iAIjq4w/edit?usp=sharing
Revisa los comentarios en línea en las celdas A2 y D1
En el ejemplo anterior, Glen de la columna Names1 se asigna a Adam en la columna Names2. Deseo escribir un código de coincidencia de aleatorización en el que Glen se mapee con todas las demás personas de la columna Nombres1 y Nombres2 sin coincidencias repetitivas. Esto es lo que he intentado hasta ahora:
Método 1: use una función de aleatorización simple () pero la coincidencia repetida se produce con una frecuencia más alta
Método 2: Usar una función aleatoria personalizada
function shuffleArray(range) { var i,j,temp; for (i=range.length-1; i>0; i--) { j = Math.floor(Math.random()*(i+1)); temp = range[i]; array[i] = array[j]; array[j] = temp; } return range; }Desafortunadamente, este método también muestra coincidencias repetidas pero a un ritmo muy inferior y no hace una coincidencia exhaustiva con todas las demás personas en ambas listas.
Cualquier ayuda sería realmente apreciada. ¡Gracias!
Puede almacenar lo que ya obtiene en una matriz y cada vez que obtenga un par, verifique primero si la matriz aún no contiene el par que encontró. Si desea todos los pares posibles, sin duplicados, puede hacer algo como esto:
const found = []; for(let i=0; i<range.length; i++){ for(let j=i+1; j<range.length; j++){ const str = `${range[i]}_${range[j]}`; if(!found.includes(str)){ found.push(str); } } }Solución1
function solution1() { const sheet = SpreadsheetApp.getActiveSpreadsheet() .getSheetByName(`Solution1`) const personsList = sheet.getRange(`A3:A`) .getValues() .filter(String) .flat() const teamsGenerated = sheet.getRange('C3:3') .getValues() .flat() .filter(String) .length let newTeam if (teamsGenerated) { const previousTeams = sheet.getRange(3, 3, personsList.length, teamsGenerated) .getValues() newTeam = randomize(personsList) while (previousTeams.some((i, index) => i.includes(newTeam[index]))) { newTeam = randomize(personsList) } sheet.getRange(3, 3+teamsGenerated, newTeam.length) .setValues(newTeam.map(i => [i])) } else { newTeam = randomize(personsList) sheet.getRange(3, 3+teamsGenerated, newTeam.length) .setValues(newTeam.map(i => [i])) } } function randomize(array) { for (let i = array.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [array[i], array[j]] = [array[j], array[i]]; } return array }Tomando todos los nombres de la primera columna, vemos si ya hay equipos generados. Si se encuentran equipos, generar un nuevo equipo donde ningún jugador esté en la misma posición que los equipos anteriores hasta que se encuentren; luego inserte en la siguiente columna disponible. Si no se encuentran equipos, inserte un equipo aleatorio.
Glen se asigna con todas las demás personas de la columna Nombres1 y Nombres2 sin coincidencias repetitivas
No está claro por qué desea hacer esto en Apps Script, porque una fórmula simple de hoja de cálculo de vainilla debería ser suficiente. Puede asignar cada nombre a cualquier otro nombre en un orden aleatorio como este:
=transpose( { A3; sort( filter( A$3:A, len(A$3:A), A$3:A <> A3 ), randarray( counta( filter( A$3:A, len(A$3:A), A$3:A <> A3 ) ) ), true ) } )
Vea la nueva hoja Solution1 en su hoja de cálculo de muestra. Para obtener otra iteración, haga clic en la casilla de verificación en la celda D2 .
El resultado esperado es solo una iteración. La próxima vez que ejecute el código, espero ver un conjunto diferente de emparejamiento para cada individuo sin repetición.
Team 1,Team 2
Eso suena como una pregunta diferente, pero puede dividir los nombres en A3:A en el número de equipos dados en B3 con esta fórmula en la celda C3 :
=arrayformula( query( query( iferror( if( { 1, 1, 0 }, floor( mod( sequence(counta(A2:A)) - { 1, 1 }, { 9^9, B3 } ), { B3, 1 } ), transpose( split( regexreplace( query( transpose( query( transpose( sort( A3:A, if( len(A3:A), randbetween( sign(row(A3:A)), 9^9 ), iferror(1/0) ), true ) & char(9) ), "", 9^9 ) ), "", 9^9 ), "\s+$", "" ), char(9) & " ", false, true ) ) ) ), "select max(Col3) where Col3 <> '' group by Col1 pivot Col2", 0 ), "offset 1", 0 ) )La fórmula creará una tabla que enumera los equipos, un equipo por columna, con los nombres divididos aleatoriamente en equipos, sin que se repitan los nombres.
Vea la nueva hoja Solution2 en su hoja de cálculo de muestra. Para obtener una división aleatoria en equipos, haga clic en la casilla de verificación en la celda B5 .