Golang:如何按星期几对切片进行排序?

I have a slice of strings which contains the days of the week like this:

days := []string{"M", "Th", "W", "F", "T", "S", "Su"}

How do I sort them so it will output like this:

[M T W Th F S Su]

starting with Monday.

You can create a map keying days to their relative order. Then you can have a type implement sort.Interface interface:

type Days []string

// map to store weekdays' relative order
var days = map[string]int{
    "M":  1,
    "T":  2,
    "W":  3,
    "Th": 4,
    "F":  5,
    "S":  6,
    "Su": 7,
}

func (d Days) Len() int      { return len(d) }
func (d Days) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
func (d Days) Less(i, j int) bool {
    return days[d[i]] < days[d[j]]
}

func main() {
    ds := Days([]string{"M", "Th", "W", "F", "T", "S", "Su"})

    sort.Sort(ds)
    fmt.Println(ds)
}

Example: https://play.golang.org/p/lzdfI-1BJK

If you want you can move days in Less method to avoid globals. But that would be severely inefficient since the map will be initialized for each element of Days.

Another implementation would be to have a pre-declared slice with the days in correct order and then use strings.Index in Less. This would perform slower but since your slice is of fixed length and very small (only 7 elements), it shouldn't be much of an issue.

You want the sort.Interface, which lets you use sort.Sort. The tricky part of this is to define the Less method, which needs to return true if one day should be considered to come before another day. I chose to do this by testing the relationship of the days to each other semantically, but you could also do this by assigning each day an int that represents its position in the week.

package main

import (
    "fmt"
    "sort"
)

type Days []string

func (d Days) Len() int {
    return len(d)
}

func (d Days) Swap(i, j int) {
    d[i], d[j] = d[j], d[i]
}

func (d Days) Less(i, j int) bool {
    switch d[i] {
        case "M":
            return true
        case "T":
            return d[j] != "M"
        case "W":
            return d[j] != "M" && d[j] != "T"
        case "Th":
            return d[j] != "M" && d[j] != "T" && d[j] != "W"
        case "F":
            return d[j] == "S" || d[j] == "Su"
        case "S":
            return d[j] == "Su"
        default:
            return false
    }
}

func main() {
    days := []string{"M", "Th", "W", "F", "T", "S", "Su"}
    sort.Sort(Days(days))
    fmt.Println(days)
}
public static void main(String[] args) {
        String[] arr = new String[] { "M", "Th", "W", "F", "T", "S", "Su" };
        // [M T W Th F S Su]
        String[] arr1 = new String[] { "M", "T", "W", "Th", "F", "S", "Su" };

        LinkedHashSet<String> h = new LinkedHashSet<String>();

        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr1.length; j++) {
                if (arr[i].equals(arr1[j])) {
                    h.add(arr[i]);

                } else {
                    arr[i] = arr1[j];
                    h.add(arr[i]);
                }

            }

        }

        System.out.println("arr = " + h);
    }

With Go 1.8 (Q1 2017) and the new sort.go implementing sort.Slice(), Paddy Foran's answer would become:

days := []string{"M", "Th", "W", "F", "T", "S", "Su"}
sort.Slice(days,  func(i, j int) bool { return less(days[i], days[j] })

less() being a func taking two strings (first letter of two days) and comparing them.

No need for Swap() or Len() anymore (done by reflection in the new sort implementation)