条件の数が可変なArray.filter()をやりたかったポエム
22927 ワード
動機
ダッシュボードみたいなの作ってて、フィルタリング条件が増えたり減ったりして実装がめんど臭い事が多々あるのであらがってみたかった。MongoのQueryみたいなの妄想したけど、andとかorの条件ネストは諦めた。
そんなに続いてるわけでもないけどコレの続き。
やりたかった事
これに
var data = [
{b: 500, g:{value: 30}},
{b: 200},
{b: 100},
{b: 300},
{string: "aiue", g:{value: 200}},
{string: "aiueo", g:{value: 300}},
]
これを
var conditionParams = [
{type: "match", "key": ["string"], "value": "ueo"},
{type: "lt", "key": ["g", "value"], "value": 400},
]
こうすると
oreoreFilter(data, conditionParams, genCondition, true);
ANDでフィルタリングされてこうなる。
// -> [ {string: "aiueo", g:{value: 300}} ]
ゆるふわ実装
// ネストされたオブジェクトをキーで取り出すやつ
function search(data,keys){
console.log(data, keys);
return keys.reduce((current, key) => {
try{
return current[key]
} catch(e) {
return undefined
}
}, data)
}
// 検索条件を組み立てるやつ
// あとで挙動を変更したり追加できるようにミドルウェアみを持たせとく
function genCondition(condition){
try{
switch(condition.type){
case "eq": return (value)=>{ return search(value, condition.key) === condition.value; }
case "gt": return (value)=>{ return search(value, condition.key) > condition.value; }
case "lt": return (value)=>{ return search(value, condition.key) < condition.value; }
case "ge": return (value)=>{ return search(value, condition.key) >= condition.value; }
case "le": return (value)=>{ return search(value, condition.key) <= condition.value; }
case "match": return (value)=>{ return new RegExp(`.*${condition.value}.*`).test(search(value, condition.key)); }
default: return ()=> false;
}
} catch (e){
return false;
}
}
// フィルタリング処理
// 対象の配列に対して実際にフィルタリングする関数
function oreoreFilter(data, conditionParams, genCondition, flg){
const conditions = conditionParams.map(genCondition)
return data.filter((value)=>{
return conditions.reduce(
(sum, condition)=>{
// 申し訳程度のAND/OR要素
if (flg){
return sum && condition(value)
}
return sum || condition(value)
}
,flg)
})
}
テスト
var data = [
{b: 500, g:{value: 30}},
{b: 200, g:{value: 500}},
{b: 200, g:{value: 300}},
{b: 100},
{b: 300},
{string: "aiue", g:{value: 200}},
{string: "aiueo", g:{value: 500}},
]
var conditionParams = [
{type: "gt", "key": ["b"], "value": 100},
{type: "lt", "key": ["b"], "value": 700},
{type: "lt", "key": ["g", "value"], "value": 400},
]
// AND検索
oreoreFilter(data, conditionParams, genCondition, true);
// -> [ {b: 500, g:{value: 30}}, {b: 200, g:{value: 300}} ]
// OR検索
oreoreFilter(data, conditionParams, genCondition, false);
// -> [
// {b: 500, g:{value: 30}},
// {b: 200, g:{value: 500}},
// {b: 200, g:{value: 300}},
// {b: 100},
// {b: 300},
// {string: "aiue", g:{value: 200}},
// ]
まとめ
とりあえず動いてる気がする。
Author And Source
この問題について(条件の数が可変なArray.filter()をやりたかったポエム), 我々は、より多くの情報をここで見つけました https://zenn.dev/okd_sh/articles/58c36749f2643cbbacc5著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Collection and Share based on the CC protocol