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 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.
61 for k
= 0; k
< len(ms
.less
)-1; k
++ {
65 // p < q, so we have a decision.
68 // p > q, so we have a decision.
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
{
81 {"glenda", "Go", 200},
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
)
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
)
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}]