Сортировка по уровню категории

#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); 

Рабочий процесс:

  1. Категория деструкции для каждого продукта
  2. Отсортируйте в порядке возрастания
  3. Фильтр в отдельных массивах, основанный на названии категории

В настоящее время меня больше всего беспокоит следующая строка:

 .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)