I'm looking to sort a slice of IP addresses (only IPV4) in Golang.
Using the native sort
package using sort.Strings()
doesn't work for obvious reasons since naturally 192.168.4.41
would be sorted in front of 192.168.4.5
By sorting the numerical value of an IP alongside the IP string in a map I came up with a way to achieve it, but it feels too manual. Is this the most efficient way to break up the IP string and sort the addresses?
https://play.golang.org/p/FUYQKuhgUq8
package main
import (
"fmt"
"strconv"
"strings"
"sort"
)
func main() {
ips := []string{
"192.168.1.5",
"69.52.220.44",
"10.152.16.23",
"192.168.3.10",
"192.168.1.4",
"192.168.1.41",
}
ipsWithInt := make(map[string]int64)
for _, ip := range ips {
ipStr := strings.Split(ip, ".")
oct0, _ := strconv.ParseInt(ipStr[0], 10, 64)
ipInt0 := oct0 * 255 * 255 * 255
oct1, _ := strconv.ParseInt(ipStr[1], 10, 64)
ipInt1 := oct1 * 255 * 255
oct2, _ := strconv.ParseInt(ipStr[2], 10, 64)
ipInt2 := oct2 * 255
oct3, _ := strconv.ParseInt(ipStr[3], 10, 64)
ipInt3 := oct3
ipInt := ipInt0 + ipInt1 + ipInt2 + ipInt3
ipsWithInt[ip] = ipInt
}
type kv struct {
Key string
Value int64
}
var ss []kv
for k, v := range ipsWithInt {
ss = append(ss, kv{k, v})
}
sort.Slice(ss, func(i, j int) bool {
return ss[i].Value < ss[j].Value
})
for _, kv := range ss {
fmt.Printf("%s\n", kv.Key)
}
}
Results:
10.152.16.23
69.52.220.44
192.168.1.4
192.168.1.5
192.168.1.41
192.168.3.10
In Go language, you can sort a slice with the help of Slice() function. This function sorts the specified slice given the provided less function. The result of this function is not stable. So for stable sort, you can use SliceStable.
You simply pass an anonymous function to the sort. Slice function. This will sort in ascending order, if you want the opposite, simply write a[i] > a[j] in the anonymous function. @LewisChan it is not restricted on int types; the int parameters are indexes to the slice, which can be a slice of strings.
Approach: The idea is to use a custom comparator to sort the given IP addresses. Since IPv4 has 4 octets, we will compare the addresses octet by octet. Check the first octet of the IP Address, If the first address has a greater first octet, then return True to swap the IP address, otherwise, return False.
Golang has a built-in sort function that can be used to sort slices of strings, integers, and floating-point numbers. Sorting is done using one of these functions: sort. Ints.
There are lots of possible ways to do it, but the easiest that comes quickly to mind would be to parse them into net.IP
s (which are just byte slices, a more accurate representation of an IP), and then sort those:
realIPs := make([]net.IP, 0, len(ips))
for _, ip := range ips {
realIPs = append(realIPs, net.ParseIP(ip))
}
sort.Slice(realIPs, func(i, j int) bool {
return bytes.Compare(realIPs[i], realIPs[j]) < 0
})
Working example here: https://play.golang.org/p/UtuvVz44_c8
This has the added advantage of working equally well with IPv6 addresses with no modifications.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With