Подтвердить что ты не робот

Иди, кусочек рун?

У меня возникли проблемы с сортировкой строк по символу (чтобы проверить, являются ли две строки анаграммами, я хочу их отсортировать и проверить на равенство).

Я могу получить представление []rune строки s следующим образом:

runes := make([]rune, len(s)) 
copy(runes, []rune(s))

И я могу сортировать такие как

someInts := []int{5, 2, 6, 3, 1, 4} // unsorted
sort.Ints(someInts)

Но rune является просто псевдонимом для int32, поэтому я должен иметь возможность вызывать

sort.Ints(runes) 

Однако я получаю сообщение об ошибке:

cannot use runes (type []rune) as type []int in function argument

Итак... как мне отсортировать фрагмент int32, int64 или int *?

РЕДАКТИРОВАТЬ: мои руны отсортированы, но мальчик, это уродливо.

type RuneSlice []rune

func (p RuneSlice) Len() int           { return len(p) }
func (p RuneSlice) Less(i, j int) bool { return p[i] < p[j] }
func (p RuneSlice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

func sorted(s string) string {
    runes := []rune(s)
    sort.Sort(RuneSlice(runes))
    return string(runes)
}

Итак, в основном, если у вас есть кусочек чего-либо, вам придется обернуть его типом, который реализует sort.Interface. Все эти реализации будут иметь те же самые тела методов (например, sort.IntSlice и sort.Float64Slice). Если это действительно так уродливо, это должно быть тогда, почему они не предоставили эти обертки WhateverSlice в пакете sort? Отсутствие дженериков начинает сильно болеть сейчас. Должен быть лучший способ сортировки вещей.

4b9b3361

Ответ 1

Используйте sort.Sort(data Interface) и реализуйте sort.Interface, см. примеры документации пакетов.

Вы не можете использовать rune, который int32 как int. Проверьте комментарий int.

int - это целочисленный тип со знаком, размер которого не менее 32 бит. Это но не псевдоним для, скажем, int32.

Ответ 2

Существует, по сути, мягко-общий способ делать то, что вы хотите.

Проверьте следующий пакет:

https://github.com/BurntSushi/ty/tree/master/fun

особенно следующий файл:

https://github.com/BurntSushi/ty/blob/master/fun/sort_test.go

Пример использования:

tosort := []int{10, 3, 5, 1, 15, 6}

fun.Sort(func(a, b int) bool {
    return b < a
}, tosort)

В этом пакете реализовано множество интересных интересных универсальных алгоритмов.

Все кредиты передаются @BurntSushi.

Ответ 3

Как точка сравнения, вот что может выглядеть, если интерфейс сортировки несколько отличается. То есть, а не интерфейс, находящийся в контейнере, что будет выглядеть, если бы интерфейс был на элементах?

package main

import (
    "fmt"
    "sort"
)

type Comparable interface {
    LessThan(Comparable) bool
}

type ComparableSlice []Comparable

func (c ComparableSlice) Len() int {
    return len(c)
}

func (c ComparableSlice) Less(i, j int) bool {
    return c[i].LessThan(c[j])
}

func (c ComparableSlice) Swap(i, j int) {
    c[i], c[j] = c[j], c[i]
}

func SortComparables(elts []Comparable) {
    sort.Sort(ComparableSlice(elts))
}

//////////////////////////////////////////////////////////////////////
// Let try using this:

type ComparableRune rune

func (r1 ComparableRune) LessThan(o Comparable) bool {
    return r1 < o.(ComparableRune)
}

func main() {
    msg := "Hello world!"

    comparables := make(ComparableSlice, len(msg))
    for i, v := range msg {
        comparables[i] = ComparableRune(v)
    }

    SortComparables(comparables)

    sortedRunes := make([]rune, len(msg))
    for i, v := range comparables {
        sortedRunes[i] = rune(v.(ComparableRune))
    }

    fmt.Printf("result: %#v\n", string(sortedRunes))
}

Здесь мы определяем интерфейс Comparable, и мы получаем наш тип ComparableRune, чтобы удовлетворить его. Но поскольку это интерфейс, нам нужно сделать неудобный бокс, чтобы перейти от rune в ComparableRune, чтобы динамическая отправка могла ударить:

    comparables := make(ComparableSlice, len(msg))
    for i, v := range msg {
        comparables[i] = ComparableRune(v)
    }

и unboxing, чтобы вернуть наши руны:

    sortedRunes := make([]rune, len(msg))
    for i, v := range comparables {
        sortedRunes[i] = rune(v.(ComparableRune))
    }

Этот подход, по-видимому, требует, чтобы мы знали, как делать машинные приемы, чтобы идти туда и обратно между интерфейсом и динамическим типом значения. Похоже, нам нужно будет использовать больше частей Go --- more mechanics --- чем подход, который использует контейнер в качестве интерфейса.

Ответ 4

Примечание. Go 1.8 будет вводить помощники для сортировки фрагментов.
См. вопрос 16721 и зафиксировать 22a2bdf Брэд Фицпатрик

var strings = [...]string{"", "Hello", "foo", "bar", "foo", "f00", "%*&^*&^&", "***"}

func TestSlice(t *testing.T) {
    data := strings
    Slice(data[:], func(i, j int) bool {
        return data[i] < data[j]
    })
}