Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Collect values in order, each containing a map

Tags:

hashmap

go

When iterating through the returned map in the code, returned by the topic function, the keys are not appearing in order.

How can I get the keys to be in order / sort the map so that the keys are in order and the values correspond?

Here is the code.

like image 954
gramme.ninja Avatar asked Apr 28 '14 00:04

gramme.ninja


People also ask

How do you sort a map using values?

Example: Sort a map by values Inside the method, we first created a list named capitalList from the map capitals . We then use the sort() method of Collections to sort elements of the list. The sort() method takes two parameters: list to be sorted and a comparator. In our case, the comparator is a lambda expression.

Is map in GO ordered?

In Go version 1.12 and later, maps are printed in key-sorted order to ease testing.

Does map stores value in sorted order?

A Map store the elements in the sorted order of keys. For example, we have a map of words and its frequency count as key – value pair i.e. Map internally stores the above elements in sorted order of keys i.e. Therefore, iterating over a map will give pair elements in above order.

How is ordered map sorted?

The map is ordered according to the natural ordering of its keys, or by a Comparator typically provided at sorted map creation time. This order is reflected when iterating over the sorted map's collection views (returned by the entrySet , keySet and values methods).


Video Answer


3 Answers

The Go blog: Go maps in action has an excellent explanation.

When iterating over a map with a range loop, the iteration order is not specified and is not guaranteed to be the same from one iteration to the next. Since Go 1 the runtime randomizes map iteration order, as programmers relied on the stable iteration order of the previous implementation. If you require a stable iteration order you must maintain a separate data structure that specifies that order.

Here's my modified version of example code: http://play.golang.org/p/dvqcGPYy3-

package main

import (
    "fmt"
    "sort"
)

func main() {
    // To create a map as input
    m := make(map[int]string)
    m[1] = "a"
    m[2] = "c"
    m[0] = "b"

    // To store the keys in slice in sorted order
    keys := make([]int, len(m))
    i := 0
    for k := range m {
        keys[i] = k
        i++
    }
    sort.Ints(keys)

    // To perform the opertion you want
    for _, k := range keys {
        fmt.Println("Key:", k, "Value:", m[k])
    }
}

Output:

Key: 0 Value: b
Key: 1 Value: a
Key: 2 Value: c
like image 126
Mingyu Avatar answered Oct 22 '22 05:10

Mingyu


All of the answers here now contain the old behavior of maps. In Go 1.12+, you can just print a map value and it will be sorted by key automatically. This has been added because it allows the testing of map values easily.

func main() {
    m := map[int]int{3: 5, 2: 4, 1: 3}
    fmt.Println(m)

    // In Go 1.12+
    // Output: map[1:3 2:4 3:5]

    // Before Go 1.12 (the order was undefined)
    // map[3:5 2:4 1:3]
}

Maps are now printed in key-sorted order to ease testing. The ordering rules are:

  • When applicable, nil compares low
  • ints, floats, and strings order by <
  • NaN compares less than non-NaN floats
  • bool compares false before true
  • Complex compares real, then imaginary
  • Pointers compare by machine address
  • Channel values compare by machine address
  • Structs compare each field in turn
  • Arrays compare each element in turn
  • Interface values compare first by reflect.Type describing the concrete type and then by concrete value as described in the previous rules.

When printing maps, non-reflexive key values like NaN were previously displayed as <nil>. As of this release, the correct values are printed.

Read more here.

like image 23
Inanc Gumus Avatar answered Oct 22 '22 07:10

Inanc Gumus


According to the Go spec, the order of iteration over a map is undefined, and may vary between runs of the program. In practice, not only is it undefined, it's actually intentionally randomized. This is because it used to be predictable, and the Go language developers didn't want people relying on unspecified behavior, so they intentionally randomized it so that relying on this behavior was impossible.

What you'll have to do, then, is pull the keys into a slice, sort them, and then range over the slice like this:

var m map[keyType]valueType
keys := sliceOfKeys(m) // you'll have to implement this
for _, k := range keys {
    v := m[k]
    // k is the key and v is the value; do your computation here
}
like image 20
joshlf Avatar answered Oct 22 '22 06:10

joshlf