#javascript #arrays #sorting #filter
Вопрос:
Просто начал погружаться в массив сортировки объектов в JavaScript, придумав следующий фрагмент. Есть ли шанс, что этот код можно каким-то образом оптимизировать для повышения производительности, или это выглядит в целом законно?
const products = [ { title: "Test product1", description: "Test description", price: 5, category: { title: 'hot_dishes', priority: 2 }, ru: { title: "Тестовый продукт", description: "пошел на хуй" } }, { title: "Test product2", description: "Test description", price: 5, category: { title: 'dessert', priority: 1 }, ru: { title: "Тестовый продукт", description: "пошел на хуй" } } ]; const sorted = products .map(({ category }) =gt; category) .sort((a, b) =gt; parseFloat(a.priority) - parseFloat(b.priority)) .map(({ title }) =gt; ( products.filter(({ category: { title: cTitle } }) =gt; title === cTitle) )); console.log(sorted);
Рабочий процесс:
- Категория деструкции для каждого продукта
- Отсортируйте в порядке возрастания
- Фильтр в отдельных массивах, основанный на названии категории
В настоящее время меня больше всего беспокоит следующая строка:
.map(({ title }) =gt; ( products.filter(({ category: { title: cTitle } }) =gt; title === cTitle) ));
Комментарии:
1. каков ваш ожидаемый результат?
2. @decpk пожалуйста, прочитайте сообщение еще раз, если неясно
3. чего вы пытаетесь достичь с помощью последнего
map
метода?4. Вы просто пытаетесь отсортировать его в соответствии с
priority
?
Ответ №1:
Вы косвенно сортируете массив с помощью priority
, но вам не нужно проходить все этапы. Вы можете просто использовать сортировку на products
также
const sorted = products.sort((a, b) =gt; a.category.priority - b.category.priority);
const products = [ { title: "Test product1", description: "Test description", price: 5, category: { title: "hot_dishes", priority: 2 }, ru: { title: "Тестовый продукт", description: "пошел на хуй" } }, { title: "Test product2", description: "Test description", price: 5, category: { title: "dessert", priority: 1 }, ru: { title: "Тестовый продукт", description: "пошел на хуй" } } ]; const sorted = products.sort((a, b) =gt; a.category.priority - b.category.priority); console.log(sorted);
/* This is not a part of answer. It is just to give the output full height. So IGNORE IT */ .as-console-wrapper { max-height: 100% !important; top: 0; }
Ответ №2:
Вы можете оптимизировать это дополнительно, и есть некоторые крайние случаи, которые следует учитывать, основываясь на форме ваших входных данных.
Единственное, что вы могли бы сделать в целом, — это нормализовать категории в отдельную коллекцию и ссылаться на идентификатор категории в продукте. Это исключило бы возможность наличия одного и того же названия категории с разными приоритетами в разных объектах.
Вы также не обработали поведение сортировки нескольких категорий с одинаковым приоритетом таким образом, чтобы гарантировать порядок сортировки, вы должны сортировать по приоритету и альфа-по названию, чтобы исправить это. Этот вызов сортировки зависит от реализации sort() в браузере и, следовательно, должен быть хорошо оптимизирован.
Ваш алгоритм сопоставляет продукт и фильтрует продукт для каждой итерации карты, что составляет O(n^2) временную сложность. Создание этого алгоритма O(n) сэкономит вам массу времени на большом наборе данных.
Я добавил фрагмент кода, который удаляет дубликаты категорий с помощью карты перед сортировкой и кэширует индекс массива категорий перед группировкой с использованием карты там же. Эти оптимизации, по общему признанию, довольно малы по сравнению с общим улучшением поиска алгоритма с одним проходом для группировки ваших продуктов.
Пустой 2-мерный массив создается из выведенного и отсортированного массива категорий. Затем мы перебираем массив продуктов и добавляем продукты в соответствующий массив категорий.
Мы сделали сортировку немного быстрее и точнее; все остальное теперь выполняется в амортизированное постоянное время.
const products = [{ title: "Test product1", description: "Test description", price: 5, category: { title: 'hot_dishes', priority: 2 }, ru: { title: "Тестовый продукт", description: "пошел на хуй" } }, { title: "Test product2", description: "Test description", price: 5, category: { title: 'dessert', priority: 1 }, ru: { title: "Тестовый продукт", description: "пошел на хуй" } } ]; const categoryComparator = (a, b) =gt; { const priorityComparison = parseFloat(a.priority) - parseFloat(b.priority) if ( priorityComparison !== 0 ) return priorityComparison return a.title.localeCompare(b) } const categoryMap = new Map() products.forEach(product =gt; categoryMap.set(product.category.title, product.category) ) const sortedCategories = Array.from(categoryMap, ([title, category]) =gt; category) .sort(categoryComparator) .map(category =gt; category.title) const categoryIndexMap = new Map([...new Set(sortedCategories)].map((category, index) =gt; [category, index])) const categorizedProductArrays = Array.from({ length: categoryIndexMap.size }, i =gt; []) products.forEach((product) =gt; categorizedProductArrays[categoryIndexMap.get(product.category.title)].push(product)) console.log(categorizedProductArrays)