将地图转换为所需的地图
Convert map into desired map
我有一个 map
结构如下:-
def map = [107:[[107, "Module 01", 1], [107, "Module New", 6]], 109:[[109, "Module 04", 1]]]
我们有一个任务来表示这个 map
如下结构:-
Application | Module 01 | Module New | Module 04
107 | 1 | 6 | 0
109 | 0 | 0 | 1
所以对于这个表示,我想过滤 map
如下:-
def outputMap = [moduleList:["Module 01", "Module New", "Module 04"], dataList:[[107:[1, 6, 0]], [109:[0, 0, 1]]]]
所以为了实现这个,我做了如下:-
def getFilteredMap(Map map) {
def moduleList = map.findResults {
it.value.findResults { it[1] }
}.flatten()
def dataList = []
map*.key.each { app ->
def tempMap = [:]
tempMap[app] = map.findResults {
it.value.findResults {
(it[0] == app) ? it[2] : 0
}
}.flatten()
dataList << tempMap
}
return ["moduleList" : moduleList, "dataList" : dataList]
}
def map = [107:[[107, "Module 01", 1], [107, "Module New", 6]], 109:[[109, "Module 04", 1]]]
def outputMap = [moduleList:["Module 01", "Module New", "Module 04"], dataList:[[107:[1, 6, 0]], [109:[0, 0, 1]]]]
assert outputMap == getFilteredMap(map)
但是如您所见,getFilteredMap()
过滤地图作为期望输出的方法不是很好。
注意 :- 模块名称可能会在此处重复,但我只希望唯一的模块名称列表表示为 Set
.
谁能提出更好的实现方法?
因为您的输入是在地图而不是漂亮的平面列表中,所以我可以推荐的最佳计划是创建 dataList
如下(collect
到其中而不是附加 [<<
] 进去)
def dataList = map*.key.collect { app ->
[(app) : map.findResults {
it.value.findResults {
(it[0] == app) ? it[2] : 0
}
}.flatten()]
}
我可能还建议使用 collectEntries
并制作 dataList
地图。
这是我得到的:
def transformMap( map ) {
// 1st collect all names to be used as 0-filled "grid-pattern"
def moduleList = map.values().inject( [] ){ res, curr ->
for( v in curr ) res << v[ 1 ]
res
}.unique()
// now fill the dataList, positioning the values according to the grid
def dataList = map.inject( [:].withDefault{ [0] * moduleList.size() } ){ res, curr ->
for( v in curr.value ) res[ curr.key ][ moduleList.indexOf( v[ 1 ] ) ] = v[ 2 ]
res
}.inject( [] ){ res, curr ->
res << [( curr.key ): curr.value]
res
}
[moduleList: moduleList, dataList: dataList]
}
def m = [107: [[107, "Module 01", 1], [107, "Module New", 6]], 109: [[109, "Module 04", 1]]]
def expected = [moduleList:["Module 01", "Module New", "Module 04"], dataList:[[107:[1, 6, 0]], [109:[0, 0, 1]]]]
assert expected == transformMap( m )
考虑将通用代码提取到新方法中。
(编辑:我还使用 collect
和 collectEntries
来清理 dataList
部分,正如 RudolphEst 所建议的那样)
def findAsFlat(map, f) {
map.findResults { it.value.findResults(f) }.flatten()
}
def getFilteredMap(Map map) {
def moduleList = findAsFlat(map, { it[1] })
def dataList = map*.key.collect { app ->
map.collectEntries ([:]) {
[app, findAsFlat(map, {(it[0] == app) ? it[2] : 0})]
}
}
return ["moduleList" : moduleList, "dataList" : dataList]
}
def map = [107:[[107, "Module 01", 1], [107, "Module New", 6]], 109:[[109, "Module 04", 1]]]
def outputMap = [moduleList:["Module 01", "Module New", "Module 04"], dataList:[[107:[1, 6, 0]], [109:[0, 0, 1]]]]
assert outputMap == getFilteredMap(map)
这比原来的更清楚,并且有利于单元测试。
我有一个 map
结构如下:-
def map = [107:[[107, "Module 01", 1], [107, "Module New", 6]], 109:[[109, "Module 04", 1]]]
我们有一个任务来表示这个 map
如下结构:-
Application | Module 01 | Module New | Module 04
107 | 1 | 6 | 0
109 | 0 | 0 | 1
所以对于这个表示,我想过滤 map
如下:-
def outputMap = [moduleList:["Module 01", "Module New", "Module 04"], dataList:[[107:[1, 6, 0]], [109:[0, 0, 1]]]]
所以为了实现这个,我做了如下:-
def getFilteredMap(Map map) {
def moduleList = map.findResults {
it.value.findResults { it[1] }
}.flatten()
def dataList = []
map*.key.each { app ->
def tempMap = [:]
tempMap[app] = map.findResults {
it.value.findResults {
(it[0] == app) ? it[2] : 0
}
}.flatten()
dataList << tempMap
}
return ["moduleList" : moduleList, "dataList" : dataList]
}
def map = [107:[[107, "Module 01", 1], [107, "Module New", 6]], 109:[[109, "Module 04", 1]]]
def outputMap = [moduleList:["Module 01", "Module New", "Module 04"], dataList:[[107:[1, 6, 0]], [109:[0, 0, 1]]]]
assert outputMap == getFilteredMap(map)
但是如您所见,getFilteredMap()
过滤地图作为期望输出的方法不是很好。
注意 :- 模块名称可能会在此处重复,但我只希望唯一的模块名称列表表示为 Set
.
谁能提出更好的实现方法?
因为您的输入是在地图而不是漂亮的平面列表中,所以我可以推荐的最佳计划是创建 dataList
如下(collect
到其中而不是附加 [<<
] 进去)
def dataList = map*.key.collect { app ->
[(app) : map.findResults {
it.value.findResults {
(it[0] == app) ? it[2] : 0
}
}.flatten()]
}
我可能还建议使用 collectEntries
并制作 dataList
地图。
这是我得到的:
def transformMap( map ) {
// 1st collect all names to be used as 0-filled "grid-pattern"
def moduleList = map.values().inject( [] ){ res, curr ->
for( v in curr ) res << v[ 1 ]
res
}.unique()
// now fill the dataList, positioning the values according to the grid
def dataList = map.inject( [:].withDefault{ [0] * moduleList.size() } ){ res, curr ->
for( v in curr.value ) res[ curr.key ][ moduleList.indexOf( v[ 1 ] ) ] = v[ 2 ]
res
}.inject( [] ){ res, curr ->
res << [( curr.key ): curr.value]
res
}
[moduleList: moduleList, dataList: dataList]
}
def m = [107: [[107, "Module 01", 1], [107, "Module New", 6]], 109: [[109, "Module 04", 1]]]
def expected = [moduleList:["Module 01", "Module New", "Module 04"], dataList:[[107:[1, 6, 0]], [109:[0, 0, 1]]]]
assert expected == transformMap( m )
考虑将通用代码提取到新方法中。
(编辑:我还使用 collect
和 collectEntries
来清理 dataList
部分,正如 RudolphEst 所建议的那样)
def findAsFlat(map, f) {
map.findResults { it.value.findResults(f) }.flatten()
}
def getFilteredMap(Map map) {
def moduleList = findAsFlat(map, { it[1] })
def dataList = map*.key.collect { app ->
map.collectEntries ([:]) {
[app, findAsFlat(map, {(it[0] == app) ? it[2] : 0})]
}
}
return ["moduleList" : moduleList, "dataList" : dataList]
}
def map = [107:[[107, "Module 01", 1], [107, "Module New", 6]], 109:[[109, "Module 04", 1]]]
def outputMap = [moduleList:["Module 01", "Module New", "Module 04"], dataList:[[107:[1, 6, 0]], [109:[0, 0, 1]]]]
assert outputMap == getFilteredMap(map)
这比原来的更清楚,并且有利于单元测试。