Supprimez les éléments du tableau avec l'épissure dans la boucle

Je souhaite implémenter une sorte de recherche en direct jQuery. Mais avant d'envoyer l'entrée au serveur, j'aimerais supprimer tous les éléments de mon tableau qui ont 3 ou moins de caractères (car en allemand, ces mots peuvent généralement être ignorés en termes de recherche). Ainsi ["this", "is", "a", "test"] devient ["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); }); }); 

Maintenant, mon problème est que tous les éléments ne sont pas supprimés dans ma boucle for. Si je par exemple tapez "c'est un test" "est" est supprimé, "a" reste. JSFIDDLE

Je pense que le problème est la boucle for, car les index du tableau changent si je supprime un élément avec une épissure, alors il continue avec l'indice "incorrect".

Peut-être que quelqu'un pourrait m'aider?

Solution 1

Vous pouvez boucler vers l'arrière, avec quelque chose comme suit:

 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/

C'est parce que l'itération progressive à travers le tableau, lorsque vous l'épisser, le tableau est modifié en place, de sorte que les éléments sont «décalés» et vous finissez par sauter l'itération de certains. La boucle vers l'arrière (avec un while ou même une boucle for ) corrige ce problème car vous n'êtes pas en train de boucler dans la direction que vous utilisez.


Solution 2

Dans le même temps, il est généralement plus rapide de générer un nouveau tableau au lieu de modifier celui-ci en place. Voici un exemple:

 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); } } 

newSearchInput ne contient que des éléments de longueur valide, et vous avez toujours les éléments originaux dans searchInput .

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


Solution 3

En plus de la deuxième solution ci-dessus, une nouvelle méthode Array.prototype similaire est disponible pour gérer cela mieux: filter . Voici un exemple:

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

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


Les références:

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

Déclaration du problème:

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

Maintenant 3 se déplace à la deuxième position et la longueur est réduite de 1, ce qui crée un problème.

Solution: une solution simple serait itérer en sens inverse lors de l'épissage.

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

Vous pouvez également utiliser la fonction $ .grep pour filtrer un tableau:

 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/

Si vous avez installé la bibliothèque lodash , ils ont un joyau sucré que vous pourriez envisager.

La fonction est _.forEachRight (itère sur les éléments d'une collection de droite à gauche)

Voici un exemple.

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