Javascript Angular5-过滤对象数组

Javascript Angular5-过滤对象数组,javascript,angular,typescript,filter,Javascript,Angular,Typescript,Filter,我正在尝试过滤产品视图,但我不知道为什么要修改原始阵列,导致过滤不正确 categories是一个数组,其对象的类别为{title,products[]} 分类视图我希望它是一个经过筛选的数组 filterByKeyword(keyword: string) { let k = keyword.toLowerCase(); this.categoriesView = this.categories.filter((c) => { for(let q = 0;

我正在尝试过滤产品视图,但我不知道为什么要修改原始阵列,导致过滤不正确

categories是一个数组,其对象的类别为{title,products[]}

分类视图我希望它是一个经过筛选的数组

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);
}
FilterByWord(关键字:字符串){
设k=keyword.toLowerCase();
this.categoriesView=this.categories.filter((c)=>{
for(设q=0;q=0;
}
});
//各类过滤产品:
for(设q=0;q{
返回p.title.toLowerCase().indexOf(k)>=0;
});
}
}
}
log(“Categories视图:”,this.categoriesView);
log(“Categories:,this.Categories”);
}

带有类别的第一个过滤器工作正常。当我深入研究产品时,问题出现了,原始数组被修改了。

在javascript中,对象是通过引用传递的。所以
categoriesView
实际上是对
categories
数组的引用,更改其中的属性将同时更改这两个属性。 如果要创建单独的对象,可以使用
angular.copy()

this.categoriesView=angular.copy(this.categories.filter((c)=>{
for(设q=0;q=0;
}
}););

查看更多信息

存在以下问题:

this.categories.filter( (c) => {...} )
数组在第一轮返回时没有正确迭代。您应该使用一个临时布尔值作为循环的缓冲区,然后返回它

此外,concider使用和重构您的代码,这将使您的代码更具可读性

this.categoriesView = this.categories.filter(c => {
    return c.products.reduce( (acc, product) => {
        return acc || product.title.toLowerCase().includes(k);
    }, false);
});

对不起,我必须介入

你的过滤和代码很糟糕

在这里,它被改写,更清晰,更简单,甚至可能会起作用:

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);
}
它应该在以下方面发挥作用:

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

Angular2中是否有AngularJS复制方法的替代品?使用数组解构创建副本:
newArray=[…oldArray]。顺便说一句,angular.copy()只适用于AngularJS(1.X),不适用于AngularJS(2+)@merlosy destructuring没有帮助嘿,谢谢!这是几个小时后找到合适解决方案的结果。。。它工作得很好,但是在过滤一次之后,原始数组只有一个产品而不是很多。这不是来自这段代码,因为您没有按照
this.categories=…
的思路编写过任何东西。你确定问题不是来自其他地方吗?@trichetriche categories是一个类别对象数组{title,products:[{…}]在从FixSt店获取数据之后,这是唯一发生的操作。一旦取出,是否有一个以上的对象?@ TreHeTrigHe,我在拒绝您在我的帖子上的编辑中所说的“减少”不是初学者可以使用的函数。如果您真的想使代码更干净和更可读,请考虑使用<代码>查找< /代码>。相反,依赖truthy/falsy值。当你查看文档时,reduce的概念非常简单。顺便说一句,我一直认为自己是初学者,过滤数组的概念非常简单,没有阅读任何文档,但他花了几个小时。我不是说你错了,我同意你的观点:你只是不能建议ad把它送给已经在挣扎的人。完美!就像魅力一样有效:)谢谢!
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));
    }
  }