JavaScript Array.filter уникальны и не блокируют пользовательский интерфейс - PullRequest
0 голосов
/ 31 января 2020

У меня есть конкретный c сценарий использования, когда в пользовательском интерфейсе должна происходить некоторая логика проверки c (по различным деловым причинам [...]). Массив может содержать до нескольких десятков или до нескольких сотен тысяч элементов (1-400К). Внешний интерфейс основан на Angular.

Первым шагом является проверка на наличие дубликатов (и сохранение их в другом массиве [...]). Это достигается с помощью следующего:

validateTargets(targets: string[]): ValidationResultObject[] {

    let result: ValidationResultObject[];
    let dups: string[] = [];

    var uniques = targets.filter( (item,index) => {
        if (targets.indexOf(item) === index) {
        return targets.indexOf(item) === index
        }
        else {
            dups.push(targets[index])
        }
    }

    //other validation logic goes here

    return result;
}

Проблема заключается в очевидном зависании пользовательского интерфейса, когда он работает против чего-либо выше 50К. В настоящее время я поставил выше в качестве обратного вызова в другой функции в setTimeout, чтобы по крайней мере позволить пользовательскому интерфейсу запускать счетчик, пока страница зависает:)

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

Я думал разбить массив на куски и запустить над Array.filter часть в al oop в setTimeout (для пользовательского интерфейса ) НО мне позже нужно сравнить куски с самим собой, так что это просто продлевает лог c! Я не чувствую себя достаточно комфортно, чтобы экспериментировать с работниками, поскольку в организации есть браузеры, которые их не поддерживают.

У кого-нибудь есть идеи, как это решить? Нет, это невозможно переместить в бэкэнд: (

С уважением

Ответы [ 3 ]

1 голос
/ 31 января 2020

Вы можете отфильтровать дубликаты намного, намного эффективнее:

let filtered = targets.reduce((result, item) => {
  result[item] = 1;
  return result;
}, {});
let noDuplicates = Object.keys(filtered);

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

0 голосов
/ 31 января 2020

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

async validateTargets(targets: string[], callback: function): {
 //...Logic
 callback(result)
}

Кроме того, для удаления дубликатов вы можете использовать

[...new Set(items)]

Примечание: это будет работать, только если массив Items содержит только примитивные значения

0 голосов
/ 31 января 2020

Я никогда не сталкивался с такой ситуацией, но я хотел бы спросить, если вы использовали Set введите javascript, поскольку он удаляет дубликаты внутри и эффективнее, чем фильтр JS Set vs Array и если у вас есть браузеры, которые не поддерживают Set, вы все равно можете использовать полифилл.

...