猿问

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

我有对象数组:


let response = [{"id": 1, "name": "Alise", "price": 400, "category": 4}];

我还有一些用于过滤的数组:


let names = ["Jessy", "Megan"];

let prices = [300, 500];

let category = [1,2,4];

我需要通过这些数组过滤数组,条件 AND 之间names, prices, category以及OR每个数组中的元素之间的条件:JessyOR Megan.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.

});

  • 首先是简单的修改过滤逻辑,不改变主过滤器

  • 第二个和第一个一样,尽管有额外的检查

  • 第三是最短的方式,但将来很难修改


繁星coding
浏览 197回答 4
4回答

侃侃尔雅

像这样的东西是清晰、简洁和可维护的。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);});您可以在此处使用对象,以便获得命名验证的好处以及能够迭代它们并检查每个validation === true. 如果您将每个验证定义为一个变量,那么您有重复的代码。例如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;});每次要添加验证时,都必须在两个地方(返回和定义)更新名称。重要的是要注意,虽然有更简洁的方法可以使用您发布的代码实现相同的结果,但这允许您在将来轻松添加更多验证类别 - 而更简洁的解决方案则不能。例如,您可以轻松地添加字符串过滤器或高级过滤器功能validations:const validations = {   matchesSearchString: !searchString || e.name.toLowerCase().startsWith(searchSting.toLowerCase()),   isAnAncientQueen: isAnAncientQueen(e.name),   /* -- snip -- */};

LEATH

我想说其他答案更简洁,但是如果您可以利用 TypeScript 的类型系统来制作一个安全且非常通用的解决方案。这种方法是否更可取取决于您在类型安全性和可维护性方面的确切需求。我的通用方法是定义一个可以应用于任何对象的过滤器类型,然后实现一个知道如何将过滤器应用于任意类型数组的函数。对于“过滤器”,这将起作用:type Filter<T> = {&nbsp; &nbsp; [P in keyof T]?: (T[P])[]}您可以将其理解为“对于Ttype的每个成员X,将有一个可选的同名Filter<T>类型数组。X[]那么过滤函数就变成了:function filter<T>(items: T[], filter: Filter<T>): T[]{&nbsp; &nbsp; // interim result for easier debugging&nbsp; &nbsp; let result =&nbsp; &nbsp; &nbsp; &nbsp; items.filter(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; item => {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // check each member in the filter&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (let key in filter) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let valueInFilter = filter[key];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // if it's empty, then it's OK&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (valueInFilter) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // otherwise the value on item MUST be found in the array on filter&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let valueInItem = item[key];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (valueInFilter.indexOf(valueInItem) == -1) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // if every check passes, keep the item&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return true;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; );&nbsp; &nbsp; return result;}把它们放在一起,它看起来像这样:let responses: IResponse[] = [&nbsp; &nbsp; { "id": 1, "name": "Alise", "price": 400, "category": 4 },&nbsp; &nbsp; { "id": 2, "name": "Bob", "price": 300, "category": 2 }];let someFilter: Filter<IResponse> = {&nbsp; &nbsp; id: [1, 2, 4],&nbsp; &nbsp; price: [300]};console.log(filter(responses, someFilter))我把它放在TypeScript Playground上,所以你可以看到所有类型检查都有效。

千巷猫影

你可以做Array.prototype.filter()满足AND条件Array.prototype.every()和OR条件Array.prototype.some():const response = [{"id": 1, "name": "Alise", "price": 400, "category": 4},{id:2, name:'Megan', price:300, category:2}],&nbsp; &nbsp; &nbsp; name = ["Jessy", "Megan"],&nbsp; &nbsp; &nbsp; price = [300, 500],&nbsp; &nbsp; &nbsp; category = [1,2,4],&nbsp; &nbsp; &nbsp; filters = {name,price,category},&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; result = response.filter(o => Object&nbsp; &nbsp; &nbsp; &nbsp; .entries(filters)&nbsp; &nbsp; &nbsp; &nbsp; .every(([key,values]) =>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; !values.length || values.some(value => o[key] == value)&nbsp; &nbsp; &nbsp; &nbsp; )&nbsp; &nbsp; &nbsp; )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;console.log(result)与Array.prototype.includes()基于 - 的方法相比,当(如果)您需要非严格匹配(例如,对某些关键字不区分大小写的部分匹配)时,它可能会更好地缩放

萧十郎

您可以获取键和值并检查includes并检查对象的所有过滤器功能。let&nbsp; &nbsp; filter = ([key, values]) => o => !values.length || values.includes(o[key]),&nbsp; &nbsp; constraints = {&nbsp; &nbsp; &nbsp; &nbsp; id: [], // empty - take all values&nbsp; &nbsp; &nbsp; &nbsp; name: ["Jessy", "Megan"],&nbsp; &nbsp; &nbsp; &nbsp; price: [300, 500],&nbsp; &nbsp; &nbsp; &nbsp; category: [1, 2, 4]&nbsp; &nbsp; }&nbsp; &nbsp; filters = Object.entries(constraints).map(filter),&nbsp; &nbsp; response = [{ id: 1, name: "Alise", price: 400, category: 4 }, { id: 2, name: "Megan", price: 300, category: 4 }],&nbsp; &nbsp; result = response.filter(o => filters.every(fn => fn(o)));console.log(result);.as-console-wrapper { max-height: 100% !important; top: 0; }
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答