如何使用"减少"功能在购物车中过滤和显示产品



我正在尝试用Javascript训练自己,对reduce有点困惑,希望能为我理解它提供一些指导。我已经做了很多研究,现在已经到了一个阶段,除了谷歌搜索之外,还需要一些清晰度。这是我的基本示例代码。。

id是购物车id,产品是商店中的产品

const ids = [4, 3, 1];
const products = [
{ id: 1, product: "Product 1" },
{ id: 2, product: "Product 2" },
{ id: 3, product: "Product 3" },
{ id: 4, product: "Product 4" },
{ id: 5, product: "Product 5" },
{ id: 6, product: "Product 6" },
{ id: 7, product: "Product 7" },
];

我需要显示购物车中的产品,所以我选择了3个选项for环路、mapfilter,最后是reduce


对于回路

// SOLUTION WITH FOR LOOP
const selectedProducts = [];
for (id of ids) {
const selectedProduct = products.filter((product) => product.id === id);
selectedProducts.push(selectedProduct);
}
console.log("selectedProducts", selectedProducts);

问题1:目前我只有7个产品。但在一家真正的商店里会有成千上万的产品。为每个id过滤数千个产品也是个好主意。有更好的方法吗?


MAP和FILTER

// SOLUTION WITH MAP
const mappedProducts = ids.map((id) => {
const [obj] = products.filter((product) => product.id === id);
return obj;
});
console.log("mappedProducts", mappedProducts);

问题2:当filter创建一个数组时,我最终得到了一个数组数组,必须销毁数组并返回对象。有没有更好的方法可以在不显式声明return的情况下直接销毁/传递对象。


减少

// SOLUTION WITH REDUCE
const initialArray = [];
const reducedProducts = products.reduce(function (acc, product) {
const productId = product.id;
if (ids.includes(product.id)) acc.push(product);
return acc;
}, initialArray);
console.log("reducedProducts", reducedProducts);
console.log("initialArray", initialArray);

问题3:我在reduce上做错了什么?

这是我第一次使用reduce,我确信我在这里做错了什么。。因为reduce被认为比formap-filter组合更紧凑,但在我的情况下,它似乎恰恰相反。我还认为减少initialValue不会发生突变。但就我而言,它正在发生变异。

如有任何帮助和建议,我们将不胜感激。

因此,为每个id过滤数千个产品是个好主意吗。有更好的方法吗?

products数组中,通过将其重组为按ID索引的对象或映射,可以轻松查找,因此您只需要使用普通的括号符号或.get来获得匹配的对象(O(1)(。

const ids = [4, 3, 1];
const products = [
{ id: 1, product: "Product 1" },
{ id: 2, product: "Product 2" },
{ id: 3, product: "Product 3" },
{ id: 4, product: "Product 4" },
{ id: 5, product: "Product 5" },
{ id: 6, product: "Product 6" },
{ id: 7, product: "Product 7" },
];
const productsById = Object.fromEntries(products.map(
obj => [obj.id, obj]
));
const result = ids.map(id => productsById[id]);
console.log(result);

有没有更好的方法可以直接销毁/传递对象而不显式声明返回。

您可以改用.find,它返回匹配的对象而不是返回数组,但这仍然是一个O(n ^ 2)过程。根据每个产品的ID对其进行索引会更好。

as reduce应该比for和map过滤器组合更紧凑,但在我的情况下,情况似乎恰恰相反。我还认为减少initialValue不会发生突变。但就我而言,它正在发生变异。

一点也不——正如您所看到的,如果不在适当的环境中使用.reduce,它确实比更标准的循环更详细。请参阅此视频。

此外,我认为减少initialValue不会发生突变。

当然可以,如果初始值是一个对象(而不是基元(-对象可以发生变化。如果您更改accumulator参数并返回它,那么下一次迭代(以及下一次和最终返回值(就是相同的对象。

请注意,下面是几个具有高阶函数的示例:

降低

products.reduce((acc, product) => {
if (ids.includes(product.id)) acc.push(product);
return acc;
}, []);

过滤器

products.filter((product) => ids.includes(product.id));
// or with destructuring 
products.filter(({ id }) => ids.includes(id));

地图和平面

products.map((product) => (ids.includes(product.id)) ? product : []).flat();

flatMap

products.flatMap((product) => (ids.includes(product.id)) ? product : []);

最新更新