2017年1月14日土曜日

Map ワイルドカードアクセス (Groovy)

Groovy
Mapオブジェクトの値取得にワイルドカードを使用してアクセスする関数を実装する。

import groovy.json.*

String json = '''
{
  "reward_id_1": 100,
  "reward_id_2": 200,
  "reward_id_3": 300,
  "other1": 10,
  "other2": 20,
  "other3": 30
}
'''

Map propertyMap(obj, String property) {
    property = property.replace("*", ".*")
    return obj.keySet()
        .findAll({ it ==~ /${property}/ })
        .collectEntries([:] as LinkedHashMap, { p -> ["$p": obj."$p"] })
}


def obj = new JsonSlurper().parseText(json)
println obj
// ==> [other1:10, other2:20, other3:30, reward_id_1:100, reward_id_2:200, reward_id_3:300]

println propertyMap(obj, "reward_id_*")
// ==> [reward_id_1:100, reward_id_2:200, reward_id_3:300]

propertyMap(obj, "reward_id_*").each { key, rewardId ->
    println rewardId
}
// ==> 100
// ==> 200
// ==> 300

propertyMapという関数に、ワイルドカードで指定したキー名を渡すと、マップにして返してくれます。
後々、連番が増えたりしても修正しなくてよいので便利かと。。


追記:
オブジェクトに対してfindAllだけで、実現できる事に気づいた。
Map propertyMap(obj, String property) {
    property = property.replace("*", ".*")
    obj.findAll { it ==~ /${property}/ }
}

ワイルドカードではなく正規表現をそのまま使うのであれば、下記一行のみでOKだった。。
it には Entryのオブジェクトが渡っているけど、マッチ演算時ではkey名で評価されているみたい。
println obj.findAll { it ==~ /reward_id_.*/ }
// ==> [reward_id_1:100, reward_id_2:200, reward_id_3:300]

最終的には、わざわざ関数作らなくても既存のGroovyメソッドで事足りるんですね。
Groovyすごいな〜

0 件のコメント:

コメントを投稿