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