Go 语言圣经 7.6 sort.Interface接口

7.6 sort.Interface接口

知识点

  • 1.sort包内置的提供了根据一些排序函数来对任何序列排序的功能
  • 2.Go语言的sort.Sort函数不会对具体的序列和它的元素做任何假设
  • 3.Go使用了一个接口类型sort.Interface来指定通用的排序算法和可能被排序到的序列类型之间的约定
  • 4.一个内置的排序算法需要三个东西:序列的长度,表示两个元素比较的结果,一种交换两个元素的方式
  • 5.接口值得动态类型如果是可以比较的,即可以作为map的key或者switch的语句操作数
  • 一个不包含任何值的nil接口值和一个刚好包含nil指针的接口值是不同的

代码

  • 1.章节中样例
  • 2.练习 7.8
  • 3.练习 7.9
func test_sort_Interface()  {

    names := []string{"1", "2", "5", "3", "4"}
    sort.Sort(StringSlice(names))
    fmt.Println(names)

    //sort.Sort(byArtist(tracks))
    //printTracks(tracks)

    fmt.Println("111===================================================================")
    //sort.Sort(sort.Reverse(byArtist(tracks)))
    //printTracks(tracks)

    fmt.Println("222===================================================================")
    //sort.Sort(byYear(tracks))
    //printTracks(tracks)

    fmt.Println("333===================================================================")
    //sort.Sort(customSort{tracks, func(x, y *Track) bool {
    //  if x.Title != y.Title {
    //      return x.Title < y.Title
    //  }
    //  if x.Year != y.Year {
    //      return x.Year < y.Year
    //  }
    //  if x.Length != y.Length {
    //      return x.Length < y.Length
    //  }
    //  return false
    //}})
    //printTracks(tracks)

    fmt.Println("444===================================================================")
    values := []int{3, 1, 4, 1}
    fmt.Println(sort.IntsAreSorted(values)) // "false"

    sort.Ints(values)
    fmt.Println(values)                     // "[1 1 3 4]"
    fmt.Println(sort.IntsAreSorted(values)) // "true"

    sort.Sort(sort.Reverse(sort.IntSlice(values)))
    fmt.Println(values)                     // "[4 3 1 1]"
    fmt.Println(sort.IntsAreSorted(values)) // "false"

    fmt.Println("555===================================================================")
    //练习 7.8
    // 模拟点击记录
    var trackss = []*Track{
        {"Go", "Delilah", "Form Roots up", 2012, length("3m37s")},
        {"Go", "Bob", "Form Roots down", 2012, length("3m37s")},
        {"Ready 2 Go", "Moby", "Moby", 1992, length("3m37s")},
        {"Go", "Bob", "As I Am", 2012, length("3m37s")},
        {"Go", "Bob", "As I Am", 2012, length("3m20s")},
        {"Go", "Martin Solveing", "Smash", 2011, length("3m37s")},
    }
    clickRecords = append(clickRecords, "Title")
    clickRecords = append(clickRecords, "Year")
    clickRecords = append(clickRecords, "Artist")
    clickRecords = append(clickRecords, "Album")
    clickRecords = append(clickRecords, "Length")
    printTracks(trackss)

    fmt.Println("666===================================================================")
    sort.Sort(multiSort{trackss, less})
    printTracks(trackss)

    //练习 7.9
    //handl := func(w http.ResponseWriter, r *http.Request) {
    //  keyWords := r.URL.Path[1:]
    //  fmt.Println(keyWords)
    //
    //  if len(keyWords) <= 0 {
    //      return
    //  }
    //  searchKey := []string{keyWords}
    //
    //  result, err := github.SearchIssues(searchKey)
    //  if err != nil {
    //      log.Fatal(err)
    //  }
    //  if err := issueList.Execute(w, result); err != nil {
    //      log.Fatal(err)
    //  }
    //}
    //http.HandleFunc("/", handl)
    //log.Println(http.ListenAndServe("localhost:8080", nil))

    http.HandleFunc("/", home)
    http.HandleFunc("/post", post)
    log.Println(http.ListenAndServe("localhost:1234", nil))
}

type User struct {
    Name string
    Date time.Time
}

var users []string

func home(w http.ResponseWriter, _ *http.Request)  {
    if err := homePage.Execute(w, users); err != nil {
        log.Printf("%v", err)
    }
}

func post(w http.ResponseWriter, r *http.Request)  {
    if err := r.ParseForm(); err != nil {
        w.WriteHeader(http.StatusInternalServerError)
        log.Printf("%v", err)
        return
    }
    fmt.Println(r.PostFormValue("but"))
    fmt.Println(r.PostFormValue("Title"))
    fmt.Println(r.PostFormValue("name"))
}
var homePage = template.Must(template.New("home").Parse(
    `<html><body>
<form action="/post"method="post"><br/>
<input type='button'value='Title'id='but1'/>
<input type='button'value='Artist'id='but2'/>
<input type='button'value='Album'id='but3'/>
<input type='button'value='Year'id='but4'/>
<input type='button'value='Length'id='but5'/>
</form></body></html>
`))

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

type Track struct {
    Title  string
    Artist string
    Album  string
    Year   int
    Length time.Duration
}

var tracks = []*Track{
    {"Go", "Delilah", "From the Roots Up", 2012, length("3m38s")},
    {"Go", "Moby", "Moby", 1992, length("3m37s")},
    {"Go Ahead", "Alicia Keys", "As I Am", 2007, length("4m36s")},
    {"Ready 2 Go", "Martin Solveig", "Smash", 2011, length("4m24s")},
}

func length(s string) time.Duration {
    d, err := time.ParseDuration(s)
    if err != nil {
        panic(s)
    }
    return d
}
func printTracks(tracks []*Track) {
    const format = "%v\t%v\t%v\t%v\t%v\t\n"
    tw := new(tabwriter.Writer).Init(os.Stdout, 0, 8, 2, ' ', 0)
    fmt.Fprintf(tw, format, "Title", "Artist", "Album", "Year", "Length")
    fmt.Fprintf(tw, format, "-----", "------", "-----", "----", "------")
    for _, t := range tracks {
        fmt.Fprintf(tw, format, t.Title, t.Artist, t.Album, t.Year, t.Length)
    }
    tw.Flush() // calculate column widths and print table
}
type byArtist []*Track
func (x byArtist) Len() int           { return len(x) }
func (x byArtist) Less(i, j int) bool { return x[i].Artist < x[j].Artist }
func (x byArtist) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }

type byYear []*Track
func (x byYear) Len() int           { return len(x) }
func (x byYear) Less(i, j int) bool { return x[i].Year < x[j].Year }
func (x byYear) Swap(i, j int)      { x[i], x[j] = x[j], x[i] }

type customSort struct {
    t    []*Track
    less func(x, y *Track) bool
}

func (x customSort) Len() int           { return len(x.t) }
func (x customSort) Less(i, j int) bool { return x.less(x.t[i], x.t[j]) }
func (x customSort) Swap(i, j int)      { x.t[i], x.t[j] = x.t[j], x.t[i] }

/*
    练习 7.8: 很多图形界面提供了一个有状态的多重排序表格插件:
        主要的排序键是最近一次点击过列头的列,
        第二个排序键是第二最近点击过列头的列,等等。
        定义一个sort.Interface的实现用在这样的表格中。
        比较这个实现方式和重复使用sort.Stable来排序的方式。
*/
type multiSortTrack []*Track

type multiSort struct {
    t    []*Track
    less func(x, y *Track) bool
}

func (x multiSort) Len() int {
    return len(x.t)
}

func (x multiSort) Less(i, j int) bool {
    return x.less(x.t[i], x.t[j])
}

func (x multiSort) Swap(i, j int) {
    x.t[i], x.t[j] = x.t[j], x.t[i]
}

var clickRecords []string

func less(x, y *Track) bool {
    for _, click := range clickRecords {
        if click == "Title" {
            if x.Title == y.Title {
                continue
            }
            return x.Title < y.Title
        }
        if click == "Year" {
            if x.Year == y.Year {
                continue
            }
            return x.Year < y.Year
        }
        if click == "Artist" {
            if x.Artist == y.Artist {
                continue
            }
            return x.Artist < y.Artist
        }
        if click == "Album" {
            if x.Album == y.Album {
                continue
            }
            return x.Album < y.Album
        }
        if click == "Length" {
            if x.Length == y.Length {
                continue
            }
            return x.Length < y.Length
        }
    }
    return false
}

备注

《Go 语言圣经》

  • 学习记录所使用的GO版本是1.8
  • 学习记录所使用的编译器工具为GoLand
  • 学习记录所使用的系统环境为Mac os
  • 学习者有一定的C语言基础

代码仓库

猜你喜欢

转载自blog.csdn.net/liushihua147/article/details/80609653
今日推荐