Хотя это старый вопрос, я бы хотел указать на пакет github.com/bradfitz/slice
.Но только в качестве примера или подтверждения концепции я бы не рекомендовал бы использовать это на самом деле (это задокументировано словом "брутто"):
Используется брутто, низкийоперации уровня, чтобы упростить сортировку произвольных фрагментов с помощью только меньшей функции, без определения нового типа с помощью операций Len и Swap.
В реальном коде я нахожу это совершенно тривиальным, быстрым, коротким,удобочитаемым и не отвлекающим просто сделать что-то вроде:
type points []point
func (p []points) Len() int { return len(p) }
func (p []points) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
func (p []points) Less(i, j int) bool {
// custom, often multi-line, comparison code here
}
Здесь gofmt
настаивает на пустой строке между строками type
и func
, но у него нет проблем с несколькими однострочнымифункции без пустых строк, и это хорошо выстраивает тела функций.Я нахожу это удобной для чтения компактной формой для таких вещей.
Что касается вашего комментария:
Кажется, что Len и Swap всегда должны иметь одну и ту же реализацию, независимо от типаstruct находится в [slice]
как раз на прошлой неделе мне нужна сортировка, которая объединяла пары элементов в срезе (для ввода в strings.NewReplacer
), что требовало тривиального изменения, такого как:
type pairByLen []string
func (p pairByLen) Len() int { return len(p) / 2 }
func (p pairByLen) Less(i, j int) bool { return len(p[i*2]) > len(p[j*2]) }
func (p pairByLen) Swap(i, j int) {
p[i*2], p[j*2] = p[j*2], p[i*2]
p[i*2+1], p[j*2+1] = p[j*2+1], p[i*2+1]
}
Это не поддерживается интерфейсом, подобным интерфейсу github.com/bradfitz/slice
.Опять же, я нахожу этот макет простым, компактным и читаемым.Хотя (возможно, даже больше в этом случае) другие могут не согласиться.