[英]Inline Conditional Map Literal in Groovy
在 Groovy 中使用 Maps/JsonBuilder 处理一些翻译/映射功能。
有可能(无需在 map 文字创建之外创建额外代码).. 有条件地包含/排除某些键/值对吗? 以下是一些事情..
def someConditional = true
def mapResult =
[
"id":123,
"somethingElse":[],
if(someConditional){ return ["onlyIfConditionalTrue":true]}
]
预期结果:如果 someConditional if false,mapResult 中将只存在 2 个键/值对。
如果 someConditional 如果为真,则所有 3 个键/值对都将存在。
请注意,如果我创建方法/并将其拆分,我确信它可以完成。为了保持简洁,我希望将内容保留在 map 创建中。
你可以帮助自己与with
:
[a:1, b:2].with{
if (false) {
c = 1
}
it
}
有一个小帮手:
Map newMap(m=[:], Closure c) {
m.with c
m
}
例如:
def m = newMap {
a = 1
b = 1
if (true) {
c = 1
}
if (false) {
d = 1
}
}
assert m.a == 1
assert m.b == 1
assert m.c == 1
assert !m.containsKey('d')
或传递初始地图:
newMap(a:1, b:2) {
if (true) {
c = 1
}
if (false) {
d = 1
}
}
由于Groovy的2.5,存在一种替代with
称为tap
。 它的工作原理with
类似with
但不返回闭包的返回值,而是委托。 所以可以这样写:
[a:1, b:2].tap{
if (false) {
c = 1
}
}
没有这样的语法,您能做的就是
def someConditional = true
def mapResult = [
"id":123,
"somethingElse":[]
]
if (someConditional) {
mapResult.onlyIfConditionalTrue = true
}
我同意Donal的观点,没有地图创建之外的代码很难。
至少您必须实现自己的ConditionalMap,这虽然有点工作,但是完全可行。
每个元素可以有自己的条件,例如
map["a"] = "A"
map["b"] = "B"
map.put("c","C", true)
map.put("d","D", { myCondition })
etc...
在这里有一个不完整的示例(我只是放置了 , get , keySet , 值和大小来说明,而没有输入-但您这里可能不需要类型?),您可能将不得不实现其他几个(isEmpty,containsKey等)。 ..)。
class ConditionalMap extends HashMap {
/** Default condition can be a closure */
def defaultCondition = true
/** Put an elemtn with default condition */
def put(key, value) {
super.put(key, new Tuple(defaultCondition, value))
}
/** Put an elemetn with specific condition */
def put(key, value, condition) {
super.put(key, new Tuple(condition, value))
}
/** Get visible element only */
def get(key) {
def tuple = super.get(key)
tuple[0] == true ? tuple[1] : null
}
/** Not part of Map , just to know the real size*/
def int realSize() {
super.keySet().size()
}
/** Includes only the "visible" elements keys */
def Set keySet() {
super.keySet().inject(new HashSet(),
{ result, key
->
def tuple = super.get(key)
if (tuple[0])
result.add(key)
result
})
}
/** Includes only the "visible" elements keys */
def Collection values() {
this.keySet().asCollection().collect({ k -> this[k] })
}
/** Includes only the "visible" elements keys */
def int size() {
this.keySet().size()
}
}
/** default condition that do not accept elements */
def map = new ConditionalMap(defaultCondition: false)
/** condition can be a closure too */
// def map = new ConditionalMap(defaultCondition : {-> true == false })
map["a"] = "A"
map["b"] = "B"
map.put("c","C", true)
map.put("d","D", false)
assert map.size() == 1
assert map.realSize() == 4
println map["a"]
println map["b"]
println map["c"]
println map["d"]
println "size: ${map.size()}"
println "realSize: ${map.realSize()}"
println "keySet: ${map.keySet()}"
println "values: ${map.values()}"
/** end of script */
您可能会将所有错误条件映射到一个公用密钥(例如"/dev/null"
, ""
等),然后在以后将其作为合同的一部分删除。 考虑以下:
def condA = true
def condB = false
def condC = false
def mapResult =
[
"id":123,
"somethingElse":[],
(condA ? "condA" : "") : "hello",
(condB ? "condB" : "") : "abc",
(condB ? "condC" : "") : "ijk",
]
// mandatory, arguably reasonable
mapResult.remove("")
assert 3 == mapResult.keySet().size()
assert 123 == mapResult["id"]
assert [] == mapResult["somethingElse"]
assert "hello" == mapResult["condA"]
您可以使用传播运算符为地图和列表执行此操作:
def t = true
def map = [
a:5,
*:(t ? [b:6] : [:])
]
println(map)
[a:5, b:6]
这在 v3 中有效,在以前的版本中没有尝试过。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.