2018-01-29 Richard Biener <rguenther@suse.de>
[official-gcc.git] / libgo / go / sort / example_multi_test.go
blobde6ec142d1c44ce616b35a79080924e6a8d4de1e
1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 package sort_test
7 import (
8 "fmt"
9 "sort"
12 // A Change is a record of source code changes, recording user, language, and delta size.
13 type Change struct {
14 user string
15 language string
16 lines int
19 type lessFunc func(p1, p2 *Change) bool
21 // multiSorter implements the Sort interface, sorting the changes within.
22 type multiSorter struct {
23 changes []Change
24 less []lessFunc
27 // Sort sorts the argument slice according to the less functions passed to OrderedBy.
28 func (ms *multiSorter) Sort(changes []Change) {
29 ms.changes = changes
30 sort.Sort(ms)
33 // OrderedBy returns a Sorter that sorts using the less functions, in order.
34 // Call its Sort method to sort the data.
35 func OrderedBy(less ...lessFunc) *multiSorter {
36 return &multiSorter{
37 less: less,
41 // Len is part of sort.Interface.
42 func (ms *multiSorter) Len() int {
43 return len(ms.changes)
46 // Swap is part of sort.Interface.
47 func (ms *multiSorter) Swap(i, j int) {
48 ms.changes[i], ms.changes[j] = ms.changes[j], ms.changes[i]
51 // Less is part of sort.Interface. It is implemented by looping along the
52 // less functions until it finds a comparison that discriminates between
53 // the two items (one is less than the other). Note that it can call the
54 // less functions twice per call. We could change the functions to return
55 // -1, 0, 1 and reduce the number of calls for greater efficiency: an
56 // exercise for the reader.
57 func (ms *multiSorter) Less(i, j int) bool {
58 p, q := &ms.changes[i], &ms.changes[j]
59 // Try all but the last comparison.
60 var k int
61 for k = 0; k < len(ms.less)-1; k++ {
62 less := ms.less[k]
63 switch {
64 case less(p, q):
65 // p < q, so we have a decision.
66 return true
67 case less(q, p):
68 // p > q, so we have a decision.
69 return false
71 // p == q; try the next comparison.
73 // All comparisons to here said "equal", so just return whatever
74 // the final comparison reports.
75 return ms.less[k](p, q)
78 var changes = []Change{
79 {"gri", "Go", 100},
80 {"ken", "C", 150},
81 {"glenda", "Go", 200},
82 {"rsc", "Go", 200},
83 {"r", "Go", 100},
84 {"ken", "Go", 200},
85 {"dmr", "C", 100},
86 {"r", "C", 150},
87 {"gri", "Smalltalk", 80},
90 // ExampleMultiKeys demonstrates a technique for sorting a struct type using different
91 // sets of multiple fields in the comparison. We chain together "Less" functions, each of
92 // which compares a single field.
93 func Example_sortMultiKeys() {
94 // Closures that order the Change structure.
95 user := func(c1, c2 *Change) bool {
96 return c1.user < c2.user
98 language := func(c1, c2 *Change) bool {
99 return c1.language < c2.language
101 increasingLines := func(c1, c2 *Change) bool {
102 return c1.lines < c2.lines
104 decreasingLines := func(c1, c2 *Change) bool {
105 return c1.lines > c2.lines // Note: > orders downwards.
108 // Simple use: Sort by user.
109 OrderedBy(user).Sort(changes)
110 fmt.Println("By user:", changes)
112 // More examples.
113 OrderedBy(user, increasingLines).Sort(changes)
114 fmt.Println("By user,<lines:", changes)
116 OrderedBy(user, decreasingLines).Sort(changes)
117 fmt.Println("By user,>lines:", changes)
119 OrderedBy(language, increasingLines).Sort(changes)
120 fmt.Println("By language,<lines:", changes)
122 OrderedBy(language, increasingLines, user).Sort(changes)
123 fmt.Println("By language,<lines,user:", changes)
125 // Output:
126 // By user: [{dmr C 100} {glenda Go 200} {gri Go 100} {gri Smalltalk 80} {ken C 150} {ken Go 200} {r Go 100} {r C 150} {rsc Go 200}]
127 // By user,<lines: [{dmr C 100} {glenda Go 200} {gri Smalltalk 80} {gri Go 100} {ken C 150} {ken Go 200} {r Go 100} {r C 150} {rsc Go 200}]
128 // By user,>lines: [{dmr C 100} {glenda Go 200} {gri Go 100} {gri Smalltalk 80} {ken Go 200} {ken C 150} {r C 150} {r Go 100} {rsc Go 200}]
129 // By language,<lines: [{dmr C 100} {ken C 150} {r C 150} {r Go 100} {gri Go 100} {ken Go 200} {glenda Go 200} {rsc Go 200} {gri Smalltalk 80}]
130 // By language,<lines,user: [{dmr C 100} {ken C 150} {r C 150} {gri Go 100} {r Go 100} {glenda Go 200} {ken Go 200} {rsc Go 200} {gri Smalltalk 80}]