Help us understand the problem. What is going on with this article?

interface{} をソートする

More than 3 years have passed since last update.

Slice のソート

シンプルに型アサーション (Type Assertions) を使います。

type Person struct {
    Name string
    Age  int
}

type People []Person

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

func Sort(v interface{}) interface{} {
    s, ok := v.(sort.Interface)
    if !ok {
        return v
    }
    sort.Sort(s)
    return s
}

func main() {
    people := People{{"Bob", 31}, {"John", 42}, {"Michael", 17}, {"Jenny", 26}}
    fmt.Println(people)  // [{Bob 31} {John 42} {Michael 17} {Jenny 26}]
    Sort(people)
    fmt.Println(people)  // [{Michael 17} {Jenny 26} {Bob 31} {John 42}]
}

interface{}sort.Interface を実装した Slice であると期待できる場合、この方法で十分でしょう。

入れ子になった Slice のソート

入れ子になった Slice もソートしたい場合は、構造体のフィールドと Slice のインデックスを走査します。

func Sort(v interface{}) {
    switch values := reflect.ValueOf(v); values.Kind() {
    case reflect.Slice:
        for i := 0; i < values.Len(); i++ {
            if values.Index(i).CanSet() {
                Sort(values.Index(i).Interface())
            }
        }
    case reflect.Struct:
        for i := 0; i < values.NumField(); i++ {
            if values.Field(i).CanSet() {
                Sort(values.Field(i).Interface())
            }
        }
    case reflect.Ptr:
        Sort(values.Elem().Interface())
    }
    if s, ok := v.(sort.Interface); ok {
        sort.Sort(s)
        return
    }
    switch s := v.(type) {
    case []int:
        sort.Ints(s)
    case []float64:
        sort.Float64s(s)
    case []string:
        sort.Strings(s)
    }
}

sort.Interface が実装されていないフィールドが []int, []float64, []string のいずれかだったときは sort パッケージに用意されているデフォルト実装でソートを行うようにしています。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした