如何搜索值和嵌套数组值
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'
}
]
产品必须可以通过 NAME
、PRICE
和 TAGS
进行搜索
我们使用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);
}
有一个具有不同值的产品对象数组。
products: object[] = [];
产品数组已填满产品。有些有 标签,有些没有。
[
{ _id: 'xxx',
name: 'ProductA',
price: '1',
tags: [ 'tag1', 'tag2' ]
},
{ _id: 'yyy',
name: 'ProductB',
price: '5'
}
]
产品必须可以通过 NAME
、PRICE
和 TAGS
我们使用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);
}