亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何按對象過濾對象數組?

如何按對象過濾對象數組?

繁星coding 2022-10-08 17:24:22
我有對象數組: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.});首先是簡單的修改過濾邏輯,不改變主過濾器第二個和第一個一樣,盡管有額外的檢查第三是最短的方式,但將來很難修改
查看完整描述

4 回答

?
侃侃爾雅

TA貢獻1801條經驗 獲得超16個贊

像這樣的東西是清晰、簡潔和可維護的。


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 -- */

};


查看完整回答
反對 回復 2022-10-08
?
LEATH

TA貢獻1936條經驗 獲得超7個贊

我想說其他答案更簡潔,但是如果您可以利用 TypeScript 的類型系統來制作一個安全且非常通用的解決方案。這種方法是否更可取取決于您在類型安全性和可維護性方面的確切需求。


我的通用方法是定義一個可以應用于任何對象的過濾器類型,然后實現一個知道如何將過濾器應用于任意類型數組的函數。


對于“過濾器”,這將起作用:


type Filter<T> = {

    [P in keyof T]?: (T[P])[]

}

您可以將其理解為“對于Ttype的每個成員X,將有一個可選的同名Filter<T>類型數組。X[]


那么過濾函數就變成了:


function filter<T>(items: T[], filter: Filter<T>): T[]{

    // interim result for easier debugging

    let result =

        items.filter(

            item => {

                // check each member in the filter

                for (let key in filter) {

                    let valueInFilter = filter[key];

                    // if it's empty, then it's OK

                    if (valueInFilter) {

                        // otherwise the value on item MUST be found in the array on filter

                        let valueInItem = item[key];

                        if (valueInFilter.indexOf(valueInItem) == -1) {

                            return false;

                        }

                    }

                }


                // if every check passes, keep the item

                return true;

            }

        );


    return result;

}

把它們放在一起,它看起來像這樣:


let responses: IResponse[] = [

    { "id": 1, "name": "Alise", "price": 400, "category": 4 },

    { "id": 2, "name": "Bob", "price": 300, "category": 2 }

];


let someFilter: Filter<IResponse> = {

    id: [1, 2, 4],


    price: [300]

};


console.log(filter(responses, someFilter))

我把它放在TypeScript Playground上,所以你可以看到所有類型檢查都有效。


查看完整回答
反對 回復 2022-10-08
?
千巷貓影

TA貢獻1829條經驗 獲得超7個贊

你可以做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}],

      name = ["Jessy", "Megan"],

      price = [300, 500],

      category = [1,2,4],

      filters = {name,price,category},

      

      

      result = response.filter(o => Object

        .entries(filters)

        .every(([key,values]) => 

          !values.length || values.some(value => o[key] == value)

        )

      )

          

console.log(result)


Array.prototype.includes()基于 - 的方法相比,當(如果)您需要非嚴格匹配(例如,對某些關鍵字不區分大小寫的部分匹配)時,它可能會更好地縮放



查看完整回答
反對 回復 2022-10-08
?
蕭十郎

TA貢獻1815條經驗 獲得超13個贊

您可以獲取鍵和值并檢查includes并檢查對象的所有過濾器功能。


let

    filter = ([key, values]) => o => !values.length || values.includes(o[key]),

    constraints = {

        id: [], // empty - take all values

        name: ["Jessy", "Megan"],

        price: [300, 500],

        category: [1, 2, 4]

    }

    filters = Object.entries(constraints).map(filter),

    response = [{ id: 1, name: "Alise", price: 400, category: 4 }, { id: 2, name: "Megan", price: 300, category: 4 }],

    result = response.filter(o => filters.every(fn => fn(o)));


console.log(result);

.as-console-wrapper { max-height: 100% !important; top: 0; }


查看完整回答
反對 回復 2022-10-08
  • 4 回答
  • 0 關注
  • 186 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號