【问题标题】:Sorting based on the category level根据类别级别排序
【发布时间】:2021-12-15 07:42:18
【问题描述】:
刚刚开始深入研究 JavaScript 中的对象数组排序,并提出了以下 sn-p。这段代码是否有可能以某种方式针对性能进行优化,或者这看起来一般合法吗?
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 }) => category)
.sort((a, b) => parseFloat(a.priority) - parseFloat(b.priority))
.map(({ title }) => (
products.filter(({ category: { title: cTitle } }) => title === cTitle)
));
console.log(sorted);
工作流程:
- 从每个产品中解构类别
- 升序排序
- 根据类别标题在单独的数组中过滤
我目前最担心的是以下行:
.map(({ title }) => (
products.filter(({ category: { title: cTitle } }) => title === cTitle)
));
【问题讨论】:
标签:
javascript
arrays
sorting
filter
【解决方案1】:
您正在使用priority 间接对数组进行排序,但您不必完成所有步骤。您也可以在products 上使用排序
const sorted = products.sort((a, b) => 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) => 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】:
您可以进一步优化这一点,根据输入的形状,有一些边缘情况需要注意。
总体而言,您可以做的是将类别标准化为单独的集合并引用产品中的类别 ID。这将消除在不同对象中具有不同优先级的相同类别标题的可能性。
您还没有以保证排序顺序的方式处理具有相同优先级的多个类别的排序行为,您应该按优先级排序并按标题排序来解决这个问题。这种排序调用依赖于浏览器对 sort() 的实现,因此应该得到很好的优化。
您的算法在映射的每次迭代中映射乘积并过滤乘积,时间复杂度为 O(n^2)。将其设为 O(n) 算法将为您在大型数据集上节省大量时间。
我添加了一个 sn-p,它在排序之前使用 Map 对类别进行重复数据删除,并在使用 Map 进行分组之前缓存类别数组索引。与为产品分组寻找单通道算法的整体改进相比,这些优化无疑是非常小的。
从重复数据删除和排序的类别数组中创建一个空的二维数组。然后我们遍历 products 数组并将产品添加到正确的类别数组中。
我们使排序更快更准确;其他一切现在都在摊销的常数时间内完成。
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) => {
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 =>
categoryMap.set(product.category.title, product.category)
)
const sortedCategories = Array.from(categoryMap, ([title, category]) => category)
.sort(categoryComparator)
.map(category => category.title)
const categoryIndexMap = new Map([...new Set(sortedCategories)].map((category, index) => [category, index]))
const categorizedProductArrays = Array.from({
length: categoryIndexMap.size
}, i => [])
products.forEach((product) =>
categorizedProductArrays[categoryIndexMap.get(product.category.title)].push(product))
console.log(categorizedProductArrays)