如何搜索值和嵌套数组值

How to search for values and nested array values

有一个具有不同值的产品对象数组。

products: object[] = [];

产品数组已填满产品。有些有 标签,有些没有。

[
  { _id: 'xxx',
    name: 'ProductA',
    price: '1',
    tags: [ 'tag1', 'tag2' ]
  },
  { _id: 'yyy',
    name: 'ProductB',
    price: '5'
  }
]

产品必须可以通过 NAMEPRICETAGS

进行搜索

我们使用Ionic 4中的ion-searchbar,ts文件中的代码如下

searchProducts(param: any): void {
  const val: string = param;
  this.resetProducts();

  if (val.trim() !== '') {
      this.products = this.products.filter(product => {
        return (
          product.name.toLowerCase().indexOf(val.toLowerCase()) > -1 ||
          product.price.toLowerCase().indexOf(val.toLowerCase()) > -1 ||
          product.tags.filter((tag: string) => {
            return tag.toLowerCase().indexOf(val.toLowerCase()) > -1
          });
        );
      });
  } else if (val.trim() === '') {
    this.resetProducts();
  }
}

每次搜索的结果都是产品数组中的所有产品。

如果我们删除标签过滤器并仅搜索名称和价格,该函数会为我们提供正确的结果。

有人可以指出正确的方向以使函数获得名称、价格和标签的 return 值吗?

编辑

product.tags.filter((tag: string) => {
            return tag.toLowerCase().indexOf(val.toLowerCase()) > -1
});


product.tags.some((tag: string) => {
                if(!tag) return false;
                return tag.toLowerCase().indexOf(val.toLowerCase()) > -1
});

编辑:
使用 some() 方法代替 filter()
filter() returns 一个新数组,其中包含此数组的所有元素,为其提供的过滤函数 returns true。
其中 as some() returns 如果此数组中至少有一个元素满足提供的测试函数。

[
  { _id: 'xxx',
    name: 'ProductA',
    price: '1',
    tags: [ 'tag1', 'tag2' ]
  },
  { _id: 'yyy',
    name: 'ProductB',
    price: '5'
  }
] 


Based on your method on searchProducts, you are filtering the tags key in the products array but product array doesn't have the `TAGS` key as per your sample above.

product.tags.filter((tag: string) => {
                return tag?tag.toLowerCase().indexOf(val.toLowerCase()) > -1:false;
});

一个简单的修复,只需添加 products.tags &&

此外,将 product.tags.filter 更改为 product.tags.some

这是因为如果没有匹配任何标签,filter 将 return [],这将在逻辑表达式中强制转换为 true

searchProducts(param: any): void {
  const val: string = param;
  this.resetProducts();

  if (val.trim() !== '') {
      this.products = this.products.filter(product => {
        return (
          product.name.toLowerCase().indexOf(val.toLowerCase()) > -1 ||
          product.price.toLowerCase().indexOf(val.toLowerCase()) > -1 ||
          product.tags && product.tags.some((tag: string) => {
            return tag.toLowerCase().indexOf(val.toLowerCase()) > -1
          });
        );
      });
  } else if (val.trim() === '') {
    this.resetProducts();
  }
}

上面的代码实际上可以转换成下面的代码来减少噪音。

searchProducts(param: any): void {
  const val: string = param;
  this.resetProducts();

  if (val.trim() !== '') {
      this.products = this.products.filter(product => 
          [
            product.name,
            product.price,
            ...(product.tags || [])
          ].some(value => value.toLowerCase().includes(val.toLowerCase()))
      );
  } else if (val.trim() === '') {
    this.resetProducts();
  }
}

这里是@WongJiaHau 发布的解决方案的更简洁版本:

const searchProducts = (param: string): void => {
  param = param.toLowerCase();
  this.resetProducts();

  if (param.trim() === '') {
    return;
  }

  const some = (list: string[]) => list.some(v => v.toLowerCase().includes(param));
  this.products = this.products
    .map(p => ({...p, tags: p.tags || []}))
    .filter(some);
}