2
\$\begingroup\$

This code snippet gets the maximum int out of a map's keys

func max(numbers map[int]bool) int {
    var maxNumber int
    for n := range numbers {
        maxNumber = n
        break
    }
    for n := range numbers {
        if n > maxNumber {
            maxNumber = n
        }
    }
    return maxNumber
}
\$\endgroup\$
0
\$\begingroup\$

The code in Abdallah Hodieb's question is good (LGTM).

I prefer the simpler, more readable form of the first for range loop.

for maxNumber = range numbers {
    break
}

The code does not depend on the iteration order over maps. The iteration order over maps is not specified and is not guaranteed to be the same from one iteration to the next.

A zero value map (nil) or an empty map reasonably returns the zero value int (0). In all other cases, for both 32- and 64-bit ints, the result is obviously correct.

For example,

package main

import "fmt"

const (
    maxInt = int(^uint(0) >> 1)
    minInt = -maxInt - 1
)

func max(numbers map[int]bool) int {
    var maxNumber int
    for maxNumber = range numbers {
        break
    }
    for n := range numbers {
        if n > maxNumber {
            maxNumber = n
        }
    }
    return maxNumber
}

func main() {
    fmt.Println("maxInt:", maxInt)
    fmt.Println("minInt:", minInt)
    var m map[int]bool
    fmt.Println("max:", max(m), m)
    m = make(map[int]bool)
    fmt.Println("max:", max(m), m)
    m = map[int]bool{maxInt: true}
    fmt.Println("max:", max(m), m)
    m = map[int]bool{1: true}
    fmt.Println("max:", max(m), m)
    m = map[int]bool{0: true}
    fmt.Println("max:", max(m), m)
    m = map[int]bool{-1: true}
    fmt.Println("max:", max(m), m)
    m = map[int]bool{minInt: true}
    fmt.Println("max:", max(m), m)
    m = map[int]bool{maxInt: true, minInt: true}
    fmt.Println("max:", max(m), m)
    m = map[int]bool{0: true, minInt: true}
    fmt.Println("max:", max(m), m)
}

Output (64-bit int):

maxInt: 9223372036854775807
minInt: -9223372036854775808
max: 0 map[]
max: 0 map[]
max: 9223372036854775807 map[9223372036854775807:true]
max: 1 map[1:true]
max: 0 map[0:true]
max: -1 map[-1:true]
max: -9223372036854775808 map[-9223372036854775808:true]
max: 9223372036854775807 map[9223372036854775807:true -9223372036854775808:true]
max: 0 map[0:true -9223372036854775808:true]

Output (32-bit int):

maxInt: 2147483647
minInt: -2147483648
max: 0 map[]
max: 0 map[]
max: 2147483647 map[2147483647:true]
max: 1 map[1:true]
max: 0 map[0:true]
max: -1 map[-1:true]
max: -2147483648 map[-2147483648:true]
max: 2147483647 map[-2147483648:true 2147483647:true]
max: 0 map[0:true -2147483648:true]
\$\endgroup\$
  • \$\begingroup\$ I didn't know you use maxNumber in the initial loop (i like it :) ) for maxNumber = range numbers { break } \$\endgroup\$ – Abdallah Hodieb Oct 25 '17 at 13:05
1
\$\begingroup\$

The code in Ainar-G's answer is flawed.

func max(numbers map[int]bool) (maxNumber int) {
    maxNumber = math.MinInt32
    for n := range numbers {
        if n > maxNumber {
            maxNumber = n
        }
    }
}

It doesn't compile: missing return at end of function.

Using build tags to distinguish between 32- and 64-bit ints is unnecessary and too complicated. Use local constants, for example,

const (
    maxInt = int(^uint(0) >> 1)
    minInt = -maxInt - 1
)

A zero value map (nil) or an empty map returns the minimum int value. Return the zero value int (0).

For example,

package main

import "fmt"

const (
    maxInt = int(^uint(0) >> 1)
    minInt = -maxInt - 1
)

func max(numbers map[int]bool) int {
    var maxNumber int
    if len(numbers) == 0 {
        return maxNumber
    }
    maxNumber = minInt
    for n := range numbers {
        if n > maxNumber {
            maxNumber = n
        }
    }
    return maxNumber
}

func main() {
    fmt.Println("maxInt:", maxInt)
    fmt.Println("minInt:", minInt)
    var m map[int]bool
    fmt.Println("max:", max(m), m)
    m = make(map[int]bool)
    fmt.Println("max:", max(m), m)
    m = map[int]bool{maxInt: true}
    fmt.Println("max:", max(m), m)
    m = map[int]bool{1: true}
    fmt.Println("max:", max(m), m)
    m = map[int]bool{0: true}
    fmt.Println("max:", max(m), m)
    m = map[int]bool{-1: true}
    fmt.Println("max:", max(m), m)
    m = map[int]bool{minInt: true}
    fmt.Println("max:", max(m), m)
    m = map[int]bool{maxInt: true, minInt: true}
    fmt.Println("max:", max(m), m)
    m = map[int]bool{0: true, minInt: true}
    fmt.Println("max:", max(m), m)
}

Output (64-bit):

maxInt: 9223372036854775807
minInt: -9223372036854775808
max: 0 map[]
max: 0 map[]
max: 9223372036854775807 map[9223372036854775807:true]
max: 1 map[1:true]
max: 0 map[0:true]
max: -1 map[-1:true]
max: -9223372036854775808 map[-9223372036854775808:true]
max: 9223372036854775807 map[9223372036854775807:true -9223372036854775808:true]
max: 0 map[0:true -9223372036854775808:true]

Output (32-bit):

maxInt: 2147483647
minInt: -2147483648
max: 0 map[]
max: 0 map[]
max: 2147483647 map[2147483647:true]
max: 1 map[1:true]
max: 0 map[0:true]
max: -1 map[-1:true]
max: -2147483648 map[-2147483648:true]
max: 2147483647 map[-2147483648:true 2147483647:true]
max: 0 map[-2147483648:true 0:true]
\$\endgroup\$
1
\$\begingroup\$

You could remove the first range by initialising maxNumber with math.MinInt(32|64) depending on the architecture. E.g. on 32-bit systems:

func max(numbers map[int]bool) (maxNumber int) {
    maxNumber = math.MinInt32
    for n := range numbers {
        if n > maxNumber {
            maxNumber = n
        }
    }
    return maxNumber
}

You can make it work with either system using build tags.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.