Rimuovi elementi dall’array con il ciclo splice in for

Voglio implementare una specie di ricerca dal vivo di jQuery. Ma prima di inviare l’input al server vorrei rimuovere tutti gli elementi nel mio array che hanno 3 o meno caratteri (perché nella lingua tedesca, quelle parole di solito possono essere ignorate in termini di ricerca) Quindi ["this", "is", "a", "test"] diventa ["this", "test"]

 $(document).ready(function() { var timer, searchInput; $('#searchFAQ').keyup(function() { clearTimeout(timer); timer = setTimeout(function() { searchInput = $('#searchFAQ').val().match(/\w+/g); if(searchInput) { for (var elem in searchInput) { if (searchInput[elem].length < 4) { //remove those entries searchInput.splice(elem, 1); } } $('#output').text(searchInput); //ajax call here } }, 500); }); }); 

Ora il mio problema è che non tutti gli elementi vengono rimossi nel mio ciclo for. Se per esempio typ “questo è un test” “è” viene rimosso, “un” rimane. JSFIDDLE

Penso che il problema sia il ciclo for perché gli indici della matrice cambiano se rimuovo un object con splice, quindi continua con l’indice “sbagliato”.

Forse qualcuno potrebbe aiutarmi?

    Soluzione 1

    Puoi eseguire il loop all’indietro, con qualcosa di simile al seguente:

     var searchInput, i; searchInput = ["this", "is", "a", "test"]; i = searchInput.length; while (i--) { if (searchInput[i].length < 4) { searchInput.splice(i, 1); } } 

    DEMO: http://jsfiddle.net/KXMeR/

    Questo perché iterando in modo incrementale attraverso l'array, quando lo si unisce, l'array viene modificato in posizione, quindi gli elementi vengono "spostati" e si finisce per saltare l'iterazione di alcuni. Il looping all'indietro (con un while o addirittura un ciclo for ) corregge questo perché non stai procedendo in loop nella direzione in cui stai eseguendo lo splicing.


    Soluzione 2

    Allo stesso tempo, di solito è più veloce generare un nuovo array invece di modificarne uno sul posto. Ecco un esempio:

     var searchInput, newSearchInput, i, j, cur; searchInput = ["this", "is", "a", "test"]; newSearchInput = []; for (i = 0, j = searchInput.length; i < j; i++) { cur = searchInput[i]; if (cur.length > 3) { newSearchInput.push(cur); } } 

    dove newSearchInput conterrà solo elementi di lunghezza validi e hai ancora gli elementi originali in searchInput .

    DEMO: http://jsfiddle.net/RYAx2/


    Soluzione 3

    Oltre alla seconda soluzione di cui sopra, è disponibile un metodo Array.prototype più recente e più Array.prototype per gestire meglio questo: filter . Ecco un esempio:

     var searchInput, newSearchInput; searchInput = ["this", "is", "a", "test"]; newSearchInput = searchInput.filter(function (value, index, array) { return (value.length > 3); }); 

    DEMO: http://jsfiddle.net/qky7D/


    Riferimenti:

     var myArr = [0,1,2,3,4,5,6]; 

    Dichiarazione problema:

     myArr.splice(2,1); \\ [0, 1, 3, 4, 5, 6]; 

    ora 3 mosse in seconda posizione e la lunghezza è ridotta di 1, il che crea problemi.

    Soluzione: una soluzione semplice sta iterando nella direzione opposta durante lo splicing.

     var i = myArr.length; while (i--) { // do your stuff } 

    Se hai installato la libreria di lodash , hanno una gem che potresti voler prendere in considerazione.

    La funzione è _.forEachRight (itera su elementi di una raccolta da destra a sinistra)

    Ecco un esempio.

     var searchInput = ["this", "is", "a", "test"]; _.forEachRight(searchInput, function(value, key) { if (value.length < 4) { searchInput.splice(key, 1); } }); 

    Puoi anche usare $ .grep per filtrare un array:

     var timer, searchInput; $('#searchFAQ').keyup(function () { clearTimeout(timer); timer = setTimeout(function () { searchInput = $('#searchFAQ').val().split(/\s+/g); // match is okay too searchInput = $.grep(searchInput, function(el) { return el.length >= 4; }); console.log(searchInput); }, 500); }); 

    http://jsfiddle.net/dfsq/4Wdp9/