Эффективный способ сортировки массива по одному ключу, но список массивов по другому ключу? - PullRequest
0 голосов
/ 02 марта 2020

У меня есть массив, который структурирован следующим образом:

[{ name: "Aardvark", count: 9 }, 
 { name: "Apple", count: 12 }, 
 { name: "Banana", count: 4 }, 
 { name: "Carrot", count: 6 }]

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

[{ name: "Apple", count: 12 }, 
 { name: "Aardvark", count: 9 },  
 { name: "Carrot", count: 6 },
 { name: "Banana", count: 4 }]

Итак, это достаточно просто. Просто сортируйте вызов что-то вроде:

arr.sort((a, b) => b.count - a.count || a.name.toLowerCase().localeCompare(b.name.toLowerCase()));

Проблема в том, что мне также нужна возможность определить, находится ли данная строка в коллекции. Например, мне нужно проверить, существует ли в коллекции Carrot.

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

Есть ли способ элегантно решить это?

1 Ответ

2 голосов
/ 02 марта 2020

Если вам нужно найти конкретное c имя в большом массиве, и у вас есть проблемы с производительностью, почему бы вам не использовать имя в качестве ключа в выделенном объекте, например:

const arr = [{ name: "Apple", count: 12 }, 
 { name: "Aardvark", count: 9 },  
 { name: "Carrot", count: 6 },
 { name: "Banana", count: 4 }];

// Initialize the object using the name as the key

const res = arr.reduce((accumulator, currentValue) => {
        (accumulator[currentValue.name] || (accumulator[currentValue.name] = [])).push(currentValue);
        return accumulator;
    }, {});

// Keep the object in sync

const handler = {
    set: function(target, property, value) {
        if(!isNaN(property)) {
            if(res[value.name]) {
                const index = res[value.name].indexOf(target[property]);
                if(index > -1) {
                    res[value.name].splice(index, 1, value);
                } else {
                    res[value.name].push(value);
                }
                
            } else {
                res[value.name] = [value];
            }

        } 

        target[property] = value;
        return true;
    }
};

const proxy = new Proxy(arr, handler);

// Use the proxy instead of the array in your whole application

proxy.push({
    name: "Mango",
    count: 13
});

console.log(proxy);
console.log(res.Mango);

proxy[0] = { name: "Apple", count: 13 };

console.log(proxy);
console.log(res.Apple);

proxy.push({ name: "Apple", count: 14 });

console.log(proxy);
console.log(res.Apple);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...