[英]Angular5 - Filtering the array of objects
I am trying to filter view of products but I don't know why original array is being modified, resulting in not correct filtering... 我正在尝试过滤产品视图,但不知道为什么要修改原始数组,导致过滤不正确...
categories is an array with objects of categories {title, products[]} category是一个数组,其中包含类别为{title,products []}的对象
categoriesView I want it to be a filtered array CategoriesView我希望它是一个过滤后的数组
filterByKeyword(keyword: string) {
let k = keyword.toLowerCase();
this.categoriesView = this.categories.filter((c) => {
for(let q = 0; q < c.products.length; q++) {
return c.products[q].title.toLowerCase().indexOf(k) >= 0;
}
});
// filter products of each category:
for(let q = 0; q < this.categoriesView.length; q++) {
for(let z = 0; z < this.categories.length; z++) {
if(this.categoriesView[q].title == this.categories[z].title){
this.categoriesView[q].products = this.categories[z].products.filter((p) => {
return p.title.toLowerCase().indexOf(k) >= 0;
});
}
}
}
console.log("Categories View: ", this.categoriesView);
console.log("Categories: ", this.categories);
}
First filter with categories works correctly. 具有类别的第一个过滤器可以正常工作。 When I dive into products problems appear and original array is modified. 当我深入研究产品时,会出现问题并修改原始阵列。
Sorry but I had to step in. 抱歉,我不得不介入。
Your filtering and code are horrible. 您的过滤和代码太可怕了。
Here it is, rewritten, clearer, simpler, and it might even should work : 在这里,它经过重写,更清晰,更简单,甚至可能可以运行:
filterByKeyword(keyword: string) {
const k = keyword.toLowerCase();
this.categoriesView = this.categories.filter(c => {
let ret = false;
for(let q of c.products) {
if(q.title.toLowerCase().includes(k)) { ret = true; }
}
return ret;
});
// Even cleaner
// this.categoriesView = this.categories.filter(c => c.products.find(p => p.title.toLowerCase().includes(k)));
for (const view of this.categoriesView) {
for (const cat of this.categories) {
if (view.title === cat.title) {
view.products = cat.products.filter(p => p.title.toLowerCase().includes(k));
}
}
}
console.log("Categories View: ", this.categoriesView);
console.log("Categories: ", this.categories);
}
there is an issue with : 有一个问题:
this.categories.filter( (c) => {...} )
Your array is not iterated properly as it returns at the first round. 您的数组在第一轮返回时未正确迭代。 You should concider using a temporary boolean as a buffer for your loop, then return it. 您应该考虑使用临时布尔值作为循环的缓冲区,然后将其返回。
Also, concider refactor your code with Array.prototype.map and Array.prototype.reduce , it will make your code a lot more readable 此外,concider使用Array.prototype.map和Array.prototype.reduce重构代码,这将使您的代码更具可读性
this.categoriesView = this.categories.filter(c => {
return c.products.reduce( (acc, product) => {
return acc || product.title.toLowerCase().includes(k);
}, false);
});
It should work: 它应该工作:
filterByKeyword(keyword: string) {
const k = keyword.toLowerCase();
this.categoriesView = this.categories.map(x => Object.assign({}, x));
this.categoriesView = this.categoriesView.filter((category) => {
category.products = category.products.filter(
(product)=> product.title.toLowerCase().includes(k));
return category.products.length>0 }
);
if(this.categoriesView.length===0){
this.categoriesView = this.categories.map(x => Object.assign({}, x));
}
}
In javascript, objects are passed by reference. 在javascript中,对象是通过引用传递的。 So categoriesView
actually IS a reference to your categories
array and changing the properties in one will change both. 因此, categoriesView
实际上是对您的categories
数组的引用,更改其中一个的属性将同时更改两者。 If you want to create a separate object, you can use angular.copy()
如果要创建一个单独的对象,可以使用angular.copy()
this.categoriesView = angular.copy(this.categories.filter((c) => {
for(let q = 0; q < c.products.length; q++) {
return c.products[q].title.toLowerCase().indexOf(k) >= 0;
}
}););
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.