3

In Go is possible to compare two strings:

package main

func main() {
    println("ab" > "ba")
    println("ab" < "ba")
}
false
true

Program exited.

https://go.dev/play/p/svkLf6R84SC

How do I perform a similar operation on two slices? e.g. []int{1,2} > []int{2,1}.

I need this to sort a slice of slices of ints. So I need an implementation of sort.Interface.

type Interface interface {
    Len() int
    Less(i, j int) bool
    Swap(i, j int)
}

It would be better if this implementation is generic.

eNV25
  • 73
  • 1
  • 7
  • @blackgreen it should be the same as strings. Strings can be thought of as an array of bytes. – eNV25 Jun 09 '22 at 13:03
  • @JimB I mean sort a slice of slices of ints, not a slice of ints. – eNV25 Jun 09 '22 at 13:04
  • 1
    `sort.Slice` is the most generic way to sort slices. You must still supply the comparison function. There is no one way to do this, so you need to make the choices yourself -- aside for the obvious first question posed by blackgreen, should the comparison modify the slices, or does it need to be done on a copy of each slice? – JimB Jun 09 '22 at 13:10
  • I basically am writing an implementation of the Less method in `sort.Interface`, that works the same way as strings. For example, sorting a `[]string` converted to a `[][]rune`. I want the implementation to work on any `[][]T` as long as `T` is in `constraints.Ordered`. – eNV25 Jun 09 '22 at 13:19
  • There's no need to work with `sort.Interface`, `sort.Slice` is going to be the most useful entry point. If you want to sort based on a parameterized `[][]T`, then you can just wrap a call to `sort.Slice` in a parameterized function. – JimB Jun 09 '22 at 13:56
  • @JimB I still need to implement less function. It doesn't make a difference. – eNV25 Jun 09 '22 at 14:16
  • 1
    A less function isn't that onerous, but since you already mentioned using `golang.org/x/exp/constraints`, why not `golang.org/x/exp/slices` too? https://go.dev/play/p/OTH7gtBP7hf – JimB Jun 09 '22 at 14:17
  • Well that's the answer. You should add as the answer, I will accept it. – eNV25 Jun 09 '22 at 14:21

1 Answers1

6

Writing a comparator and a less function for sort.Slices would be the most effective way to do this within the standard library. Stepping outside of that slightly (until generics usage within the standard library is finalized), in Go 1.18 we can use the golang.org/x/exp/constraints and golang.org/x/exp/slices packages to generically sort a slice of slices of ordered values: https://go.dev/play/p/MA0lY6POVFR

func SortSlices[T constraints.Ordered](s [][]T) {
    sort.Slice(s, func(i, j int) bool {
        return slices.Compare(s[i], s[j]) < 0
    })
}

Documentation about slices.Compare:

Compare compares the elements of s1 and s2. The elements are compared sequentially, starting at index 0, until one element is not equal to the other. The result of comparing the first non-matching elements is returned. If both slices are equal until one of them ends, the shorter slice is considered less than the longer one. The result is 0 if s1 == s2, -1 if s1 < s2, and +1 if s1 > s2. Comparisons involving floating point NaNs are ignored.

blackgreen
  • 34,072
  • 23
  • 111
  • 129
JimB
  • 104,193
  • 13
  • 262
  • 255