如何过滤对象数组并仅获取其条目不等于另一个数组对象的任何条目的对象?

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' 选项。 我有两个数组:uniqueProductsselectedFiltersuniqueProducts 包含要在 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; }