I have recently discovered the following Python/Go comparison:
Python:
sort(a, key=lambda x: x[1] / x[2], reverse=True)
Go:
type Entry struct {
u float64
v float64
}
type EntrySlice []Entry
func (p EntrySlice) Len() int {
return len(p)
}
func (p EntrySlice) Less(i, j int) bool {
return p[i].u / p[i].v > p[j].u / p[j].v
}
func (p EntrySlice) Swap(i, j int) {
p[i], p[j] = p[j], p[i]
}
// a []Entry
sort.Sort(EntrySlice(a))
The proposal:
Introduce sort.Array helper function:
sort.Array(a, func(i,j int) bool { return a[i].u / a[i].v > a[j].u / a[j].v})
Currently, it's impossible to implement such a helper, because
reflect.Value has func Index(i int) Value to access an element in the
array, but there's no way to set the element of the array.
Thus, sort.Array needs reflect.Value.SetIndex(i int, ev Value) to be
implemented.
Two possible improvements:
1. put sort.Array into sort/util package, because it introduces
dependency on reflect package.
2. implement reflect.Value.SwapIndex(i,j int) which will speed up the
sort, because no intermediate values are created.
Comments?
Ivan Krasin
However, I would at least point out that the comparison
you posted is flawed. You can't charge the struct definition
to the sorting (it would have existed anyway), and most
people would use 1-line method implementations:
Python:
sort(a, key=lambda x: x[1] / x[2], reverse=True)
Go:
type ByRatioReverse []Entry
func (b ByRatioReverse) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
func (b ByRatioReverse) Len() int { return len(b) }
func (b ByRatioReverse) Less(i, j int) bool { return b[i].u/b[i].v >
b[j].u/b[j].v }
sort.Sort(ByRatioReverse(a))
That's really not a big deal in the grand scheme of
things. If all you do is sort things, and you never
use the same sort order or container type twice,
then yes you have a 5x code blowup. Maybe you
should use Python in that case. That's okay.
Russ
I'm guessing (hoping) go uses a stable sort?