Подтвердить что ты не робот

Удалить элементы из массива с помощью сплайсинга в цикле

Я хочу реализовать какой-то живой поиск в 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, потому что индексы массива меняются, если я удаляю элемент со сплайсированием, поэтому он продолжается с "неправильным" индексом.

Возможно, кто-нибудь может мне помочь?

4b9b3361

Ответ 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/