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.
12 // A Change is a record of source code changes, recording user, language, and delta size.
19 type lessFunc
func(p1
, p2
*Change
) bool
21 // multiSorter implements the Sort interface, sorting the changes within.
22 type multiSorter
struct {
27 // Sort sorts the argument slice according to the less functions passed to OrderedBy.
28 func (ms
*multiSorter
) Sort(changes
[]Change
) {
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
{
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 is either Less or
53 // !Less. Note that it can call the less functions twice per call. We
54 // could change the functions to return -1, 0, 1 and reduce the
55 // number of calls for greater efficiency: an exercise for the reader.
56 func (ms
*multiSorter
) Less(i
, j
int) bool {
57 p
, q
:= &ms
.changes
[i
], &ms
.changes
[j
]
58 // Try all but the last comparison.
60 for k
= 0; k
< len(ms
.less
)-1; k
++ {
64 // p < q, so we have a decision.
67 // p > q, so we have a decision.
70 // p == q; try the next comparison.
72 // All comparisons to here said "equal", so just return whatever
73 // the final comparison reports.
74 return ms
.less
[k
](p
, q
)
77 var changes
= []Change
{
80 {"glenda", "Go", 200},
86 {"gri", "Smalltalk", 80},
89 // ExampleMultiKeys demonstrates a technique for sorting a struct type using different
90 // sets of multiple fields in the comparison. We chain together "Less" functions, each of
91 // which compares a single field.
92 func Example_sortMultiKeys() {
93 // Closures that order the Change structure.
94 user
:= func(c1
, c2
*Change
) bool {
95 return c1
.user
< c2
.user
97 language
:= func(c1
, c2
*Change
) bool {
98 return c1
.language
< c2
.language
100 increasingLines
:= func(c1
, c2
*Change
) bool {
101 return c1
.lines
< c2
.lines
103 decreasingLines
:= func(c1
, c2
*Change
) bool {
104 return c1
.lines
> c2
.lines
// Note: > orders downwards.
107 // Simple use: Sort by user.
108 OrderedBy(user
).Sort(changes
)
109 fmt
.Println("By user:", changes
)
112 OrderedBy(user
, increasingLines
).Sort(changes
)
113 fmt
.Println("By user,<lines:", changes
)
115 OrderedBy(user
, decreasingLines
).Sort(changes
)
116 fmt
.Println("By user,>lines:", changes
)
118 OrderedBy(language
, increasingLines
).Sort(changes
)
119 fmt
.Println("By language,<lines:", changes
)
121 OrderedBy(language
, increasingLines
, user
).Sort(changes
)
122 fmt
.Println("By language,<lines,user:", changes
)
125 // By user: [{dmr C 100} {glenda Go 200} {gri Smalltalk 80} {gri Go 100} {ken Go 200} {ken C 150} {r Go 100} {r C 150} {rsc Go 200}]
126 // 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}]
127 // 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}]
128 // By language,<lines: [{dmr C 100} {ken C 150} {r C 150} {gri Go 100} {r Go 100} {ken Go 200} {glenda Go 200} {rsc Go 200} {gri Smalltalk 80}]
129 // 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}]