Удалить элементы из массива с помощью сплайсинга в цикле
Я хочу реализовать какой-то живой поиск в jQuery.
Но перед отправкой ввода на сервер я хотел бы удалить все элементы в моем массиве, которые имеют 3 или менее символа (потому что на немецком языке эти слова обычно можно игнорировать с точки зрения поиска)
Итак, ["this", "is", "a", "test"]
становится ["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);
});
});
Теперь моя проблема заключается в том, что не все элементы удаляются в цикле for.
Если я, например, тип "это тест", то "удаляется", "a" остается.
JSFIDDLE
Я думаю, что проблема заключается в цикле for, потому что индексы массива меняются, если я удаляю элемент со сплайсированием, поэтому он продолжается с "неправильным" индексом.
Возможно, кто-нибудь может мне помочь?
Ответы
Ответ 1
Решение 1
Вы можете перемещаться назад, с чем-то вроде следующего:
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/
Это происходит из-за постепенного повторения массива при его объединении, массив изменяется на месте, поэтому элементы "сдвинуты", и вы в конечном итоге пропускаете итерацию некоторых. Зацикливание назад (с циклом while
или даже for
) исправляет это, потому что вы не зацикливаете в том направлении, в котором вы сращиваете.
Решение 2
В то же время обычно быстрее генерировать новый массив вместо того, чтобы изменять его. Вот пример:
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
будет содержать только допустимые элементы длины, и у вас все еще есть исходные элементы в searchInput
.
DEMO: http://jsfiddle.net/RYAx2/
Решение 3
В дополнение ко второму выше решению аналогичный более новый метод Array.prototype
доступен для более эффективного управления: filter
. Вот пример:
var searchInput, newSearchInput;
searchInput = ["this", "is", "a", "test"];
newSearchInput = searchInput.filter(function (value, index, array) {
return (value.length > 3);
});
DEMO: http://jsfiddle.net/qky7D/
Литература:
Ответ 2
var myArr = [0,1,2,3,4,5,6];
Проблема:
myArr.splice(2,1);
\\ [0, 1, 3, 4, 5, 6];
теперь 3 движения во второй позиции, а длина уменьшается на 1, что создает проблему.
Решение: Простое решение будет выполнять итерацию в обратном направлении при сращивании.
var i = myArr.length;
while (i--) {
// do your stuff
}
Ответ 3
Если у вас установлена библиотека lodash, у них есть сладкий камень, который вы, возможно, захотите рассмотреть.
Функция _. forEachRight (итерации по элементам коллекции справа налево)
Вот пример.
var searchInput = ["this", "is", "a", "test"];
_.forEachRight(searchInput, function(value, key) {
if (value.length < 4) {
searchInput.splice(key, 1);
}
});
Ответ 4
Вы также можете использовать $. grep функцию фильтрации массива:
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/