Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/474.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何按对象过滤对象数组?_Javascript_Typescript - Fatal编程技术网

Javascript 如何按对象过滤对象数组?

Javascript 如何按对象过滤对象数组?,javascript,typescript,Javascript,Typescript,我有一组对象: let response = [{"id": 1, "name": "Alise", "price": 400, "category": 4}]; 我还有一些用于过滤的数组: let names = ["Jessy", "Megan"]; let prices = [300, 500]; let category = [1,2,4]; 我需要通过以下数组过滤数组:带有条件的数组和介于名称、价格、类别之间的数组,以及带有条件的数组或每个数组中元素之间的数组:Jessy或Mega

我有一组对象:

let response = [{"id": 1, "name": "Alise", "price": 400, "category": 4}];
我还有一些用于过滤的数组:

let names = ["Jessy", "Megan"];
let prices = [300, 500];
let category = [1,2,4];
我需要通过以下数组过滤数组:带有条件的数组和介于
名称、价格、类别之间的数组,以及带有条件的数组
或每个数组中元素之间的数组:
Jessy
Megan

我提出了这个解决方案:

const filterByCategory = (response: IResponse[], filterBy: any[]) => response.filter((e: IResponse) => filterBy.indexOf(e.category) > -1);
const filterByPrice =  (response: IResponse[], filterBy: any[]) => response.filter((e: IResponse) => e.price in filterBy);
filter() {
  let filtered = filterByCategory(response, category);
  filtered = filterByPrice(filtered, prices);
}
filter() {
   let filtered = [];
   if (category && category.length) {
      filtered = filterByCategory(response, category);
   }

   if (prices && prices.length) {
       filtered = filterByCategory(filtered, category);
   }

}
let filtered = response.filter((element) => {
    return category && category.indexOf(e.category) > -1 && 
    prices && prices.indexOf(e.price) > -1 && etc.
});
那我就不知道该怎么打电话了:

单向:

const filterByCategory = (response: IResponse[], filterBy: any[]) => response.filter((e: IResponse) => filterBy.indexOf(e.category) > -1);
const filterByPrice =  (response: IResponse[], filterBy: any[]) => response.filter((e: IResponse) => e.price in filterBy);
filter() {
  let filtered = filterByCategory(response, category);
  filtered = filterByPrice(filtered, prices);
}
filter() {
   let filtered = [];
   if (category && category.length) {
      filtered = filterByCategory(response, category);
   }

   if (prices && prices.length) {
       filtered = filterByCategory(filtered, category);
   }

}
let filtered = response.filter((element) => {
    return category && category.indexOf(e.category) > -1 && 
    prices && prices.indexOf(e.price) > -1 && etc.
});
秒:

const filterByCategory = (response: IResponse[], filterBy: any[]) => response.filter((e: IResponse) => filterBy.indexOf(e.category) > -1);
const filterByPrice =  (response: IResponse[], filterBy: any[]) => response.filter((e: IResponse) => e.price in filterBy);
filter() {
  let filtered = filterByCategory(response, category);
  filtered = filterByPrice(filtered, prices);
}
filter() {
   let filtered = [];
   if (category && category.length) {
      filtered = filterByCategory(response, category);
   }

   if (prices && prices.length) {
       filtered = filterByCategory(filtered, category);
   }

}
let filtered = response.filter((element) => {
    return category && category.indexOf(e.category) > -1 && 
    prices && prices.indexOf(e.price) > -1 && etc.
});
第三名:

const filterByCategory = (response: IResponse[], filterBy: any[]) => response.filter((e: IResponse) => filterBy.indexOf(e.category) > -1);
const filterByPrice =  (response: IResponse[], filterBy: any[]) => response.filter((e: IResponse) => e.price in filterBy);
filter() {
  let filtered = filterByCategory(response, category);
  filtered = filterByPrice(filtered, prices);
}
filter() {
   let filtered = [];
   if (category && category.length) {
      filtered = filterByCategory(response, category);
   }

   if (prices && prices.length) {
       filtered = filterByCategory(filtered, category);
   }

}
let filtered = response.filter((element) => {
    return category && category.indexOf(e.category) > -1 && 
    prices && prices.indexOf(e.price) > -1 && etc.
});
  • 首先是简单地修改过滤逻辑,不改变主过滤器
  • 第二个和第一个一样,尽管有额外的检查
  • 第三种是最短的方式,但将来很难修改

类似的内容清晰、简洁且易于维护

const filteredItems = response.filter(e => {
    const validations = {
       containsCategory: category && category.includes(e.category),
       containsPrice: prices && prices.includes(e.price),
       containsName: names && names.includes(e.name),
    };

    return Object.values(validations).every(v => v);
});
您可以在这里使用一个对象,这样您就可以获得命名验证的好处,并且能够迭代验证并检查每个
验证===true
。如果您将每个验证定义为一个变量,那么您有重复的代码。e、 g

const filteredItems = response.filter(e => {
   const containsCategory = category && category.includes(e.category);
   const containsPrice = prices && prices.includes(e.price);
   const containsName = names && names.includes(e.name);

   return containsName && containsPrice && containsName;
});
每次要添加验证时,都必须在两个位置(返回和定义)更新名称

需要注意的是,虽然有更简洁的方法可以实现与您发布的代码相同的结果,但这允许您在将来轻松添加更多的验证类别,而更简洁的解决方案则不行

例如,您也可以轻松地将字符串筛选器或高级筛选器函数添加到
验证中

const validations = {
   matchesSearchString: !searchString || e.name.toLowerCase().startsWith(searchSting.toLowerCase()),
   isAnAncientQueen: isAnAncientQueen(e.name),
   /* -- snip -- */
};

您可以使用键和值,使用
includes
进行检查,并使用对象的所有过滤功能进行检查

let
过滤器=([key,values])=>o=>!values.length | | values.includes(o[键]),
约束={
id:[],//为空-获取所有值
姓名:[“杰西”、“梅根”],
价格:[300500],
类别:[1、2、4]
}
过滤器=对象。条目(约束)。映射(过滤器),
响应=[{id:1,名称:“Alise”,价格:400,类别:4},{id:2,名称:“Megan”,价格:300,类别:4}],
结果=response.filter(o=>filters.every(fn=>fn(o));
控制台日志(结果)
。作为控制台包装{max height:100%!important;top:0;}
您可以使用和执行
条件或
条件:

const response=[{“id”:1,“name”:“Alise”,“price”:400,“category”:4},{id:2,name:'Megan',price:300,category:2}],
姓名=[“杰西”,“梅根”],
价格=[300500],
类别=[1,2,4],
过滤器={name,price,category},
结果=响应.过滤器(o=>对象
.条目(过滤器)
.every([键,值])=>
!values.length | | values.some(value=>o[key]==value)
)
)

log(result)
我想说,其他答案更简洁,但如果您可以利用TypeScript的类型系统来创建一个安全且非常通用的解决方案。这种方法是否可取取决于您在类型安全性和可维护性方面的确切需求

我的一般方法是定义一个可以应用于任何对象的过滤器类型,然后实现一个知道如何将过滤器应用于任意类型数组的函数

对于“过滤器”,这将起作用:

类型过滤器={
[P在keyof T中]?:(T[P])[]
}
您可以将其理解为“对于
T
X
类型的每个成员,
Filter
将具有具有相同名称的
X[]
类型的可选数组

然后,过滤器功能变为:

函数过滤器(项:T[],过滤器:过滤器):T[]{
//临时结果,以便调试
让结果=
items.filter(
项目=>{
//检查过滤器中的每个成员
用于(让输入过滤器){
设valueInFilter=过滤器[键];
//如果是空的,那就没问题了
if(值填充器){
//否则,必须在筛选器上的数组中找到项上的值
让valueInItem=项[键];
if(valueInFilter.indexOf(valueInItem)=-1){
返回false;
}
}
}
//如果每次检查都通过,则保留该项目
返回true;
}
);
返回结果;
}
把它们放在一起,看起来是这样的:

let响应:i响应[]=[
{“id”:1,“name”:“Alise”,“price”:400,“category”:4},
{“id”:2,“name”:“Bob”,“price”:300,“category”:2}
];
让someFilter:Filter={
id:[1,2,4],
价格:[300]
};
日志(过滤器(响应,someFilter))

我将这些放在一起,以便您可以看到所有类型检查都有效。

数组。prototype.includes
是集合值之间的OR过滤器,而
&
是您要查找的AND过滤器:

let response=[{“id”:1,“name”:“Megan”,“price”:500,“category”:4}];
让名字=[“杰西”,“梅根];
让价格=[300500];
设类别=[1,2,4];
常量filteredItems=response.filter(项=>{
返回名称。包括(项目名称)和
价格。包括(项目价格)&&
类别。包括(项目。类别);
});
console.log(filteredItems)

看起来validations对象是多余的?validation对象在那里,因此您可以显式地命名每个验证-这使得以后更容易维护和修改。如果其他程序员遇到该函数,他们可以很容易地看到发生了什么。因此,
find()
如果没有匹配项,则返回undefined。这意味着
过滤器中的对象可以具有
undefined
值。这就是为什么您使用
every
迭代对象的所有值,以仅过滤
true
值,而不是undefined