Saurabh Gaur Saurabh Gaur - 3 months ago 35
Groovy Question

Convert map into desired map

I have a

map
with structure as below :-

def map = [107:[[107, "Module 01", 1], [107, "Module New", 6]], 109:[[109, "Module 04", 1]]]


We have a task to represent this
map
as below structure :-

Application | Module 01 | Module New | Module 04
107 | 1 | 6 | 0
109 | 0 | 0 | 1


So for this representation, I want to filter
map
as below :-

def outputMap = [moduleList:["Module 01", "Module New", "Module 04"], dataList:[[107:[1, 6, 0]], [109:[0, 0, 1]]]]


So for achieving this, I have done as below :-

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)


But as you can see
getFilteredMap()
method to filter map as desire output is not very good.

Note :- Module name may be repeated here, but I want only unique module Names list means as
Set
.

Can anyone suggest better way to achieve this?

Answer

Consider extracting the common code into a new method.

(Edit: I have also used collect and collectEntries to clean up the dataList section, as suggested by 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)

This is clearer than the original and would facilitate unit tests.