оптимизировать поиск через большой массив строк JS? - PullRequest
9 голосов
/ 20 октября 2010

Если у меня большой массив строк JavaScript, который содержит более 10000 элементов, как мне быстро выполнить поиск по нему?

Сейчас у меня есть массив строк JavaScript, в котором хранится описание задания, и я "м, позволяя пользователю динамически фильтровать возвращенный список при вводе в поле ввода.

Итак, скажем, у меня есть строковый массив, подобный так:
var descArr = {"flipping burgers", "pumping gas", "delivering mail"};

, и пользователь хочетискать: "p"

Как я могу быстро найти массив строк, содержащий более 10000 описаний? Очевидно, я не могу отсортировать массив описаний, так как они являются описаниями, поэтому бинарный поиски поскольку пользователь может выполнять поиск по "p" или "pi" или любой комбинации букв, этот частичный поиск означает, что я не могу использовать ассоциативные массивы (например, searchDescArray["pumping gas"]) для ускорения поиска.

Есть идеи у кого-нибудь?

Ответы [ 5 ]

20 голосов
/ 20 октября 2010

Поскольку движки регулярных выражений в реальных браузерах сходят с ума с точки зрения скорости, как насчет этого? Вместо массива передайте гигантскую строку и разделите слова идентификатором. Пример:

  • Строка "flipping burgers""pumping gas""delivering mail"
  • Регулярное выражение: "([^"]*ping[^"]*)"

С переключателем /g для глобального вы получаете все совпадения. Убедитесь, что пользователь не ищет ваш разделитель строк.

Вы даже можете добавить идентификатор в строку с чем-то вроде:

  • Строка "11 flipping burgers""12 pumping gas""13 delivering mail"
  • Регулярное выражение: "(\d+) ([^"]*ping[^"]*)"

  • Пример: http://jsfiddle.net/RnabN/4/ (30000 строк, ограничение результатов до 100)

4 голосов
/ 20 октября 2010

Нет способа ускорить поиск начального массива без внесения некоторых изменений.Вы можете ускорить последовательный поиск, кэшируя результаты и динамически сопоставляя их с шаблонами.

1.) Настройте формат данных.Это делает начальные поиски несколько быстрее.По сути, вы предварительно кэшируете.

var data = {
    a : ['Ant farm', 'Ant massage parlor'],
    b : ['Bat farm', 'Bat massage parlor']
    // etc
}

2.) Настройте механизм кэширования.

var searchFor = function(str, list, caseSensitive, reduce){
    str = str.replace(/(?:^\s*|\s*$)/g, ''); // trim whitespace
    var found = [];
    var reg = new RegExp('^\\s?'+str, 'g' + caseSensitive ? '':'i');
    var i = list.length;
    while(i--){
        if(reg.test(list[i])) found.push(list[i]);
        reduce && list.splice(i, 1);
    }
}

var lookUp = function(str, caseSensitive){
    str = str.replace(/(?:^\s*|\s*$)/g, ''); // trim whitespace
    if(data[str]) return cache[str];
    var firstChar = caseSensitive ? str[0] : str[0].toLowerCase();
    var list = data[firstChar];
    if(!list) return (data[str] = []);
    // we cache on data since it's already a caching object.
    return (data[str] = searchFor(str, list, caseSensitive)); 
}

3.) Используйте следующий скрипт для создания объекта предварительного кэширования.Я предлагаю вам запустить его один раз и использовать JSON.stringify для создания статического объекта кэша.(или сделайте это на сервере)

// we need lookUp function from above, this might take a while
var preCache = function(arr){
    var chars = "abcdefghijklmnopqrstuvwxyz".split('');
    var cache = {};
    var i = chars.length;
    while(i--){
        // reduce is true, so we're destroying the original list here.
        cache[chars[i]] = searchFor(chars[i], arr, false, true);
    }
    return cache;
}

Возможно, немного больше кода, чем вы ожидали, но оптимизация и производительность не бесплатны.

1 голос
/ 20 октября 2010

Я не могу воспроизвести проблему, я создал наивную реализацию, и большинство браузеров выполняют поиск по 10000 15 символьным строкам за однозначное число миллисекунд.Я не могу тестировать в IE6, но я бы не поверил, что это более чем в 100 раз медленнее, чем в самых быстрых браузерах, которые все равно будут практически мгновенными.Обратите внимание, что время создания не имеет отношения к проблеме, оно просто для того, чтобы получить некоторые данные для работы.)

Одна вещь, которую вы могли бы сделать неправильно, это попытка отобразить все результаты, что было бы весьмазадание, когда пользователь ввел только одну букву или комбинацию из общих букв.

1 голос
/ 20 октября 2010

Это может не быть ответом для вас, так как я делаю некоторые предположения о вашей настройке, но если у вас есть код на стороне сервера и база данных, вам будет гораздо лучше сделать обратный вызов AJAX, чтобы получить сокращениесписок результатов и использование базы данных для фильтрации (так как они очень хороши в подобных вещах).

Помимо преимущества для базы данных, вы также выиграете от того, что не будете выводить так многоданных (10000 переменных) в веб-интерфейс - если вы вернете только те, которые вам нужны, вы сэкономите немало трафика.

0 голосов
/ 20 октября 2010

Я предлагаю попробовать готовую JS-функцию, например autocomplete из jQuery.Это быстро и имеет много параметров для настройки.

Посмотрите демонстрацию автозаполнения jQuery

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...