Sono riuscito a farlo a mano. Il codice è chilometrico ovviamente.
Ho duplicato per le tre textarea esattamente gli stessi range di slice, quindi la distribuzione non è proprio ideale.
Sicuramente troverete soluzioni più performanti.
Sono riuscito a farlo a mano. Il codice è chilometrico ovviamente.
Ho duplicato per le tre textarea esattamente gli stessi range di slice, quindi la distribuzione non è proprio ideale.
Sicuramente troverete soluzioni più performanti.
doppio
Ultima modifica di U235; 24-11-2018 a 21:39
una roba del genere?
html:
codice:<inputtype="number"id="nGruppi"value="7"/> <textareaid="a">"A-Ciccio", "A-Franco", "A-Gino", "A-Pino"</textarea> <textareaid="b">"B-Pippo", "B-Gianni", "B-Giorgio", "B-Mario"</textarea> <textareaid="c">"C-Giovanni", "C-Aldo", "C-Sergio", "C-Luigi"</textarea> <buttononclick="test();">test</button> <divid="result"></div>
js
codice:function test() { var arrayGlobale = new Array(); arrayGlobale[0] = document.getElementById("a").value.split(','); arrayGlobale[1] = document.getElementById("b").value.split(','); arrayGlobale[2] = document.getElementById("c").value.split(','); var nGruppi = document.getElementById("nGruppi").value; var result = document.getElementById("result"); result.innerHTML = ""; var elements = new Array(nGruppi); for (var i = 0; i < nGruppi; i++) { elements[i] = document.createElement("ul"); result.appendChild(elements[i]); } var nextGruppo = 0; var nextComponente = 0; var totComponenti = 0; for (var i = 0; i < arrayGlobale.length; i++) totComponenti += arrayGlobale[i].length; while (totComponenti > 0) { nextGruppo = nextGruppo < nGruppi ? nextGruppo : 0; var random = Math.floor(Math.random() * ((arrayGlobale[nextComponente].length - 1) + 1)); var ul = document.createElement("li") ul.innerHTML = arrayGlobale[nextComponente][random]; elements[nextGruppo++].appendChild(ul); arrayGlobale[nextComponente].splice(random, 1); if (arrayGlobale[nextComponente].length < 1) { arrayGlobale.splice(nextComponente, 1); } totComponenti = 0; for (var i = 0; i < arrayGlobale.length; i++) totComponenti += arrayGlobale[i].length; } }
ovviamente si puo scrivere di meglio, ma buttata giù "al volo" credo possa andare bene...
Ultima modifica di U235; 24-11-2018 a 21:44
questa parte qui dentro il while:
non serve, basta fare :codice:totComponenti =0; for(var i =0; i < arrayGlobale.length; i++) totComponenti += arrayGlobale[i].length;
codice:totComponenti --;
Bene, mi pare buona la soluzione di U235, io per il momento non ho saputo fare di meglio, complimenti anche da parte mia
Installa Forum HTML.it Toolset per una fruizione ottimale del Forum
Ciao,
grazie.
In realtà si potrebbe rendere più dinamico (e anche più corto) in modo che si possa avere un numero indefinito di liste "source", e dare ad ognuna un ordine di importanza, ad esempio tramite l'id della textarea (a>b ecc.):
html (con ordine casuale delle textarea):
js:codice:<input type="number" id="nGruppi" value="7" /> <textarea id="a">"A-Ciccio", "A-Franco", "A-Gino", "A-Pino"</textarea> <textarea id="d">"D-Nicola", "D-Marco", "D-Pietro", "D-Riccardo"</textarea> <textarea id="c">"C-Giovanni", "C-Aldo", "C-Sergio", "C-Luigi"</textarea> <textarea id="b">"B-Pippo", "B-Gianni", "B-Giorgio", "B-Mario"</textarea> <button onclick="test();">test</button>
in pratica è lo stesso di prima solo che ora recupero tutti i tags textarea e li ordino in base all'id. In più visto che tanto stavo già ciclando nel while ho eliminato il for per creare gli elementi e quello per contare gli elementi interni (conto il numero di elementi dell'arrayGlobale) e le variabili che non servivano quindi totComponenti e nextComponente (tanto serve sempre 0).codice:function test() { var nGruppi = document.getElementById("nGruppi").value; var result = document.getElementById("result"); result.innerHTML = ""; var elements = new Array(); var arrayGlobale = Array.prototype.slice.call(document.getElementsByTagName("textarea")) .sort((el1, el2) => el1.id < el2.id ? -1 : 1) .map((currentValue, index, arr) => currentValue.value.split(',')); var nextGruppo = 0; while (arrayGlobale.length > 0) { if (!elements[nextGruppo]) { elements[nextGruppo] = document.createElement("ul"); result.appendChild(elements[nextGruppo]); }; nextGruppo = nextGruppo < nGruppi ? nextGruppo : 0; var random = Math.floor(Math.random() * ((arrayGlobale[0].length - 1) + 1)); var li = document.createElement("li") li.innerHTML = arrayGlobale[0][random]; elements[nextGruppo++].appendChild(li); arrayGlobale[0].splice(random, 1); if (arrayGlobale[0].length < 1) arrayGlobale.shift(); } }
Beh, veramente notevole.
Un'implementazione che potrebbe essere utile e interessante è quella di creare una text-area in cui inserire nomi che NON possono essere inseriti nello stesso gruppo. Pensi che sia possibile?
ciao,
beh diciamo che dovresti farti un controllo incrociato. Ad esempio una cosa del genere:
in modo da poterlo riutilizzare e fare un controllo preventivo sull'array che poi andrai ad utilizzare. Ad esempio così:codice:Array.prototype.twoDimArrayDistinct = function () { var found = []; var result = this.map(function (arr) { return arr.filter(function (item) { var res = found.indexOf(item) < 0&&item!=""; if (res) found.push(item); return res; }); }); return result; };
Come vedi la funzione è rimasta la stessa, ma aggiungo in coda all'array un twoDimArrayDistinct() e un filter per evitare che ci finiscano dentro array vuoti.codice:function test() { var nGruppi = document.getElementById("nGruppi").value; var result = document.getElementById("result"); result.innerHTML = ""; var elements = new Array(); var arrayGlobale = Array.prototype.slice.call(document.getElementsByTagName("textarea")) .sort((el1, el2) => el1.id < el2.id ? -1 : 1) .map((currentValue) => currentValue!=""? currentValue.value.split(','):[]) .twoDimArrayDistinct() .filter((arr) => arr.length > 0); var nextGruppo = 0; while (arrayGlobale.length > 0) { if (!elements[nextGruppo]) { elements[nextGruppo] = document.createElement("ul"); result.appendChild(elements[nextGruppo]); }; nextGruppo = nextGruppo < nGruppi ? nextGruppo : 0; var random = Math.floor(Math.random() * arrayGlobale[0].length); var li = document.createElement("li") li.innerHTML = arrayGlobale[0][random]; elements[nextGruppo++].appendChild(li); arrayGlobale[0].splice(random, 1); if (arrayGlobale[0].length < 1) arrayGlobale.shift(); } }
Ma questo in realtà è un controllo fatto DOPO il click, per cui non impedisce di scrivere doppioni, li "ripulisce" quando legge i valori nella funzione "test", quindi in realtà per rispondere alla tua domanda ci vuole altro:
e nelle textarea usi un onkeyup="check(this);" in modo da chiamare la funzione al rilascio del tasto, in questo modo quando risulta un doppione (mentre scrivi) questo viene cancellato automaticamente.codice:function check(el) { var last = el.value.slice(-1); var elements = Array.prototype.slice.call(document.getElementsByTagName("textarea")); var arrayGlobale = elements.map((currentValue) => currentValue.value.split(',')).twoDimArrayDistinct(); var index = 0; elements.forEach((element) => element.value = arrayGlobale[index++].length > 0 ? arrayGlobale[index - 1].join(",") : null); if (last == ",") el.value = el.value + ","; }
Ovviamente questa è solo una prova di concetto, credo che non sarebbe indicato eseguire il check ad ogni digitazione, sopratutto se le liste sono grandi. A limite potresti farlo con il carattere divisore, ovvero prima di fare tutto il lavoro dentro check(el) ti accerti che sia stato premuto il carattere "divisore" (la virgola in questo caso), in modo da limitare il controllo solo quando l'utente "dichiara" di aver scritto tutto l'item.
per fare una prova:
codice:<input type="number" id="nGruppi" value="7" /> <textarea onkeyup="check(this);" id="a">A-Ciccio,A-Franco,A-Gino,A-Pino</textarea> <textarea onkeyup="check(this);" id="d">D-Nicola,D-Marco,D-Pietro,D-Riccardo</textarea> <textarea onkeyup="check(this);" id="c">C-Giovanni,C-Aldo,C-Sergio,C-Luigi</textarea> <textarea onkeyup="check(this);" id="b">B-Pippo,B-Gianni,B-Giorgio,B-Mario</textarea> <textarea onkeyup="check(this);" id="b">B-Pippo,B-Gianni,B-Giorgio,B-Mario,B-Mario</textarea> <button onclick="test();">test</button> <div id="result"></div>