如何过滤对象数组并仅获取其条目不等于另一个数组对象的任何条目的对象?
How to filter through an array of objects and only get the objects whose entries do not equal any entry from another array's objects?
基本上,当您过滤 table 产品时,我需要做一个 'all except' 选项。
我有两个数组:uniqueProducts
和 selectedFilters
。
uniqueProducts
包含要在 table 中显示的产品对象。
selectedFilters
包含预 select 过滤器的对象。
uniqueProducts
数组的对象如下所示:
{category: 'radio', price: '50', manufacturer: 'sony', production_date: '2020/05/30'}
下面是 selectedFilters
数组的对象:
{type: 'manufacturer', value: 'sony', status: true}
{type: 'category', value: 'radio', status: true}
因为价格过滤器有最小值和最大值,所以我会在准备好对象数组后过滤价格。
过滤也不包括production_date
。
所以,selectedFilters objects's type
属性 可以是上面两个中的任何一个。
我需要做的是通过uniqueProducts
进行过滤,只获取与selectedFilters
.[=24=中对象的任何类型和值都不匹配的对象]
换句话说,当您 select 过滤产品并单击 'all except' 时,您必须查看所有不符合该过滤器的产品。希望你明白我的意思。
我试过这样做:
uniqueProducts.forEach((product)=>{
for(let i = 0; i < selectedFilters.length; i++) {
if(product[selectedFilters[i].type] !== selectedFilters[i].value) {
allExceptArray.push(product)
}
}
})
我也试过嵌套 for..loops
和各种其他条件,但我一直 运行 的问题是,每次对象的特定 属性 都不会匹配,它会被推入数组,即使同一对象的另一个 属性 确实匹配。
谁能帮我弄清楚这里的逻辑是怎么做的?
以下方法基于单个 reduce
task where the reducer function incorporates a some
基于 filter/comparison 的任务。
filter/match 过程的实现方式是,只要一个 filter-configuration 的条件与单个项目 属性.
匹配,就假定匹配
function isMatchingItem({ type: key, value }, item) {
return item[key] === value;
}
function collectNonMatchingItem({ filters = [], result = [] }, item) {
if (
!filters.some(filter => isMatchingItem(filter, item))
) {
result.push(item);
}
return { filters, result };
}
const uniqueProducts = [
{ category: 'radio', price: '50', manufacturer: 'sony', production_date: '2020/05/30' },
{ category: 'radio', price: '70', manufacturer: 'philips', production_date: '2020/05/30' },
{ category: 'tv', price: '500', manufacturer: 'sony', production_date: '2020/05/30' },
{ category: 'tv', price: '650', manufacturer: 'philips', production_date: '2020/05/30' },
{ category: 'console', price: '900', manufacturer: 'sony', production_date: '2020/05/30' },
{ category: 'console', price: '700', manufacturer: 'nintendo', production_date: '2020/05/30' },
];
const selectedFilters = [
{ type: 'manufacturer', value: 'sony', status: true },
{ type: 'category', value: 'radio', status: true },
];
const result = uniqueProducts.reduce(collectNonMatchingItem, {
filters: selectedFilters,
result: [],
}).result;
console.log({ result });
.as-console-wrapper { min-height: 100%!important; top: 0; }
编辑
"... So, I need to now do the case when prices have been selected too and need to be all except filtered. I know I have to filter through the result
array, but again, how do I make sure that only the objs that DO NOT match the min/max price are taken? ... My first instinct now is to just reverse the condition, i.e. do if NOT match, but then, what do I put inside? It doesn't feel proper to leave the if block empty. How should I go about doing it?" – user17144382
cause 的最终价格过滤应基于 filter
. Since the OP wants to filter every item where the item's price
value is not within a certain min/max price range, one just needs to adapt the price value comparison accordingly. More important, filter
like most of the Array
methods supports a second argument, the thisArg
,它被应用为任何支持 this
绑定的过滤函数的上下文。
因此,想出一个正确命名的过滤器函数的附加实现和用法并不难...
function isOutOfBoundPriceRange(item) {
const { minPrice, maxPrice } = this;
const price = parseFloat(item.price);
return (price < parseFloat(minPrice)) || (price > parseFloat(maxPrice));
}
function isMatchingItem({ type: key, value }, item) {
return item[key] === value;
}
function collectNonMatchingItem({ filters = [], result = [] }, item) {
if (
!filters.some(filter => isMatchingItem(filter, item))
) {
result.push(item);
}
return { filters, result };
}
const uniqueProducts = [
{ category: 'cellphone', price: '19', manufacturer: 'nokia', production_date: '2020/05/30' },
{ category: 'radio', price: '50', manufacturer: 'sony', production_date: '2020/05/30' },
{ category: 'radio', price: '70', manufacturer: 'philips', production_date: '2020/05/30' },
{ category: 'tv', price: '500', manufacturer: 'sony', production_date: '2020/05/30' },
{ category: 'tv', price: '650', manufacturer: 'philips', production_date: '2020/05/30' },
{ category: 'console', price: '900', manufacturer: 'sony', production_date: '2020/05/30' },
{ category: 'console', price: '700', manufacturer: 'nintendo', production_date: '2020/05/30' },
];
const selectedFilters = [
{ type: 'manufacturer', value: 'sony', status: true },
{ type: 'category', value: 'radio', status: true },
];
const priceFilter = {
minPrice: 20,
maxPrice: 650,
};
const result = uniqueProducts.reduce(collectNonMatchingItem, {
filters: selectedFilters,
result: [],
}).result.filter(isOutOfBoundPriceRange, priceFilter);
console.log({ priceFilter, result });
.as-console-wrapper { min-height: 100%!important; top: 0; }
基本上,当您过滤 table 产品时,我需要做一个 'all except' 选项。
我有两个数组:uniqueProducts
和 selectedFilters
。
uniqueProducts
包含要在 table 中显示的产品对象。
selectedFilters
包含预 select 过滤器的对象。
uniqueProducts
数组的对象如下所示:
{category: 'radio', price: '50', manufacturer: 'sony', production_date: '2020/05/30'}
下面是 selectedFilters
数组的对象:
{type: 'manufacturer', value: 'sony', status: true}
{type: 'category', value: 'radio', status: true}
因为价格过滤器有最小值和最大值,所以我会在准备好对象数组后过滤价格。
过滤也不包括production_date
。
所以,selectedFilters objects's type
属性 可以是上面两个中的任何一个。
我需要做的是通过uniqueProducts
进行过滤,只获取与selectedFilters
.[=24=中对象的任何类型和值都不匹配的对象]
换句话说,当您 select 过滤产品并单击 'all except' 时,您必须查看所有不符合该过滤器的产品。希望你明白我的意思。
我试过这样做:
uniqueProducts.forEach((product)=>{
for(let i = 0; i < selectedFilters.length; i++) {
if(product[selectedFilters[i].type] !== selectedFilters[i].value) {
allExceptArray.push(product)
}
}
})
我也试过嵌套 for..loops
和各种其他条件,但我一直 运行 的问题是,每次对象的特定 属性 都不会匹配,它会被推入数组,即使同一对象的另一个 属性 确实匹配。
谁能帮我弄清楚这里的逻辑是怎么做的?
以下方法基于单个 reduce
task where the reducer function incorporates a some
基于 filter/comparison 的任务。
filter/match 过程的实现方式是,只要一个 filter-configuration 的条件与单个项目 属性.
匹配,就假定匹配function isMatchingItem({ type: key, value }, item) {
return item[key] === value;
}
function collectNonMatchingItem({ filters = [], result = [] }, item) {
if (
!filters.some(filter => isMatchingItem(filter, item))
) {
result.push(item);
}
return { filters, result };
}
const uniqueProducts = [
{ category: 'radio', price: '50', manufacturer: 'sony', production_date: '2020/05/30' },
{ category: 'radio', price: '70', manufacturer: 'philips', production_date: '2020/05/30' },
{ category: 'tv', price: '500', manufacturer: 'sony', production_date: '2020/05/30' },
{ category: 'tv', price: '650', manufacturer: 'philips', production_date: '2020/05/30' },
{ category: 'console', price: '900', manufacturer: 'sony', production_date: '2020/05/30' },
{ category: 'console', price: '700', manufacturer: 'nintendo', production_date: '2020/05/30' },
];
const selectedFilters = [
{ type: 'manufacturer', value: 'sony', status: true },
{ type: 'category', value: 'radio', status: true },
];
const result = uniqueProducts.reduce(collectNonMatchingItem, {
filters: selectedFilters,
result: [],
}).result;
console.log({ result });
.as-console-wrapper { min-height: 100%!important; top: 0; }
编辑
"... So, I need to now do the case when prices have been selected too and need to be all except filtered. I know I have to filter through the
result
array, but again, how do I make sure that only the objs that DO NOT match the min/max price are taken? ... My first instinct now is to just reverse the condition, i.e. do if NOT match, but then, what do I put inside? It doesn't feel proper to leave the if block empty. How should I go about doing it?" – user17144382
cause 的最终价格过滤应基于 filter
. Since the OP wants to filter every item where the item's price
value is not within a certain min/max price range, one just needs to adapt the price value comparison accordingly. More important, filter
like most of the Array
methods supports a second argument, the thisArg
,它被应用为任何支持 this
绑定的过滤函数的上下文。
因此,想出一个正确命名的过滤器函数的附加实现和用法并不难...
function isOutOfBoundPriceRange(item) {
const { minPrice, maxPrice } = this;
const price = parseFloat(item.price);
return (price < parseFloat(minPrice)) || (price > parseFloat(maxPrice));
}
function isMatchingItem({ type: key, value }, item) {
return item[key] === value;
}
function collectNonMatchingItem({ filters = [], result = [] }, item) {
if (
!filters.some(filter => isMatchingItem(filter, item))
) {
result.push(item);
}
return { filters, result };
}
const uniqueProducts = [
{ category: 'cellphone', price: '19', manufacturer: 'nokia', production_date: '2020/05/30' },
{ category: 'radio', price: '50', manufacturer: 'sony', production_date: '2020/05/30' },
{ category: 'radio', price: '70', manufacturer: 'philips', production_date: '2020/05/30' },
{ category: 'tv', price: '500', manufacturer: 'sony', production_date: '2020/05/30' },
{ category: 'tv', price: '650', manufacturer: 'philips', production_date: '2020/05/30' },
{ category: 'console', price: '900', manufacturer: 'sony', production_date: '2020/05/30' },
{ category: 'console', price: '700', manufacturer: 'nintendo', production_date: '2020/05/30' },
];
const selectedFilters = [
{ type: 'manufacturer', value: 'sony', status: true },
{ type: 'category', value: 'radio', status: true },
];
const priceFilter = {
minPrice: 20,
maxPrice: 650,
};
const result = uniqueProducts.reduce(collectNonMatchingItem, {
filters: selectedFilters,
result: [],
}).result.filter(isOutOfBoundPriceRange, priceFilter);
console.log({ priceFilter, result });
.as-console-wrapper { min-height: 100%!important; top: 0; }