Sorting Map values in descending order with Groovy

11,940

Solution 1

Just do:

​def m = [a:​5, b:12, c:3, d:9]
def sorted = m.sort { a, b -> b.value <=> a.value }

Solution 2

To do the sorting, Tim's implementation is the way to go. But if you're just wondering why your example code doesn't work as you expect, the answer is that the variable 'sorted' needs to be of type LinkedHashMap, rather than just HashMap. You can set it explicitly:

Map<String,Integer> sorted = new LinkedHashMap<String,Integer>()

Or, just do this:

Map<String,Integer> sorted = [:]
Share:
11,940
smeeb
Author by

smeeb

Updated on June 19, 2022

Comments

  • smeeb
    smeeb almost 2 years

    I have a Map<String,Integer> whose entries (keys) need to be sorted in order of descending value. For instance, if the map looks like:

    "a" => 5
    "b" => 3
    "c" => 12
    "d" => 9
    

    The after sorting it needs to look like:

    "c" => 12
    "d" => 9
    "a" => 5
    "b" => 3
    

    My best attempt thus far:

    def test() {
        Map<String,Integer> toSort = new HashMap<String,Integer>()
        toSort.put("a", 5)
        toSort.put("b", 3)
        toSort.put("c", 12)
        toSort.put("d", 9)
    
        Map<String,Integer> sorted = sortMapDesc(toSort)
        sorted.each {
            println "${it.key} has a value of ${it.value}."
        }
    }
    
    def sortMapDesc(Map<String,Integer> toSort) {
        println "Sorting..."
        println toSort
    
        // The map of properly sorted entries.
        Map<String,Integer> sorted = new HashMap<String,Integer>()
    
        // Keep scanning the map for the key with the highest value. When we find
        // it, add it as the next entry to the 'sorted' map, and then zero it out
        // so it won't show up as the highest on subsequent scans/passes. Stop scanning
        // when the entire 'toSort' map contains keys with zeros.
        while(!mapIsAllZeros(toSort)) {
            int highest = -1
            String highestKey = ""
            toSort.each {
                if(it.value > highest) {
                    highest = it.value
                    highestKey = it.key
                }
            }
    
            toSort.put(highestKey, 0)
            sorted.put(highestKey, highest)
        }
    
        sorted
    }
    
    def mapIsAllZeros(Map<String,Integer> toCheck) {
        toCheck.values().every{!it}
    }
    

    When I run test() I get the following output:

    Sorting...
    [d:9, b:3, c:12, a:5]
    d has a value of 9.
    b has a value of 3.
    c has a value of 12.
    a has a value of 5.
    

    Where am I going wrong here?