tags:

views:

215

answers:

2

In Go, what's the easiest way to get the keys in a map sorted alphabetically? This is the shortest way I can do it:

package main

import "container/vector"
import "fmt"
import "sort"

func main() {
    m := map[string]string {"b":"15", "z":"123123", "x":"sdf", "a":"12"}
    var keys vector.StringVector;
    for k,_ := range ( m ) {
            keys.Push(k)
    }
    sort.Sort( &keys )
    fmt.Printf("%v\n", keys)
}
A: 

Since a plain 'string []keys' does not meet the sort.Interface (the compiler says 'missing Len() (int)'), there isn't much you can do to reduce that code (and even though attempting to use 'string []keys' avoids using a StringVector, it adds a couple of lines to the code (for the declaration of an index variable and the incrementing of it).

So, unless there is an automatic way of converting from a map to a vector of the keys that I've not been able to divine from the documentation, what you have here is about as succinct as it gets.

To use the sort package, the type must provide the sort.Interface. You have to have a mechanism to access the data in the container type to access the elements by integer indexes, as well as the Len(), LessThan() and Swap() methods.


Code that fails to compile, and is in any case one line longer than the original:

package main

import "fmt"
import "sort"

func main() {
    m := map[string]string{"b": "15", "z": "123123", "x": "sdf", "a": "12"}
    var keys []string
    var i int
    for k, _ := range (m) {
        keys[i] = k
        i++
    }
    sort.Sort(&keys)
    fmt.Printf("%v\n", keys)
}

The compilation error:

so-2038508-jl.go:14: *[]string is not sort.Interface
    missing Len() (int)
Jonathan Leffler
If you change the var keys []string statement to var keys = make(sort.StringArray, len(m)) you will be able to compile and you will not get the index out of range error.
peterSO
Thanks, PeterSO; I have some reading/learning left to do. One interesting tid-bit; the optional semi-colons seems to be relatively new. I had to update the GO compiler on my machine to get the compilation to work without semicolons.
Jonathan Leffler
Go implemented a large change to the syntax rules for semicolons on December 22, 2009.release.2009-12-22:http://groups.google.com/group/golang-nuts/msg/ed2c38932ba1bd44Semicolons in Go:http://groups.google.com/group/golang-nuts/msg/7facb7856f017791
peterSO
Thanks for the links - happened just before I joined the mailing list. Also happened somewhat after I installed Go on machine 1 but before I installed it on machine 2. Which led to some schizophrenia trying to work out why stuff that almost compiled on machine 2 failed dramatically on machine 1. I've done an update of both compilers now. (Is there a way to get the compiler version out of the compiler? Options '-v', '-V' and '--version' do not seem to do the job; I'm not surprised at the latter.)
Jonathan Leffler
There is no way to get the compiler version from the compiler. version string? : http://groups.google.com/group/golang-nuts/msg/c23458f7f96595a6. For the source code version: cd go command and then hg identify command.
peterSO
+3  A: 

You are sorting an array of strings using StringVector. To minimize overhead, you could sort an array of strings.

package main

import (
    "fmt"
    "sort"
)

func main() {
    m := map[string]string{"b": "15", "z": "123123", "x": "sdf", "a": "12"}
    mk := make([]string, len(m))
    i := 0
    for k, _ := range m {
        mk[i] = k
        i++
    }
    sort.SortStrings(mk)
    fmt.Println(mk)
}
peterSO