mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			132 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			132 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
// Copyright 2013 The Go Authors. All rights reserved.
 | 
						|
// Use of this source code is governed by a BSD-style
 | 
						|
// license that can be found in the LICENSE file.
 | 
						|
 | 
						|
package sort_test
 | 
						|
 | 
						|
import (
 | 
						|
	"fmt"
 | 
						|
	"sort"
 | 
						|
)
 | 
						|
 | 
						|
// A Change is a record of source code changes, recording user, language, and delta size.
 | 
						|
type Change struct {
 | 
						|
	user     string
 | 
						|
	language string
 | 
						|
	lines    int
 | 
						|
}
 | 
						|
 | 
						|
type lessFunc func(p1, p2 *Change) bool
 | 
						|
 | 
						|
// multiSorter implements the Sort interface, sorting the changes within.
 | 
						|
type multiSorter struct {
 | 
						|
	changes []Change
 | 
						|
	less    []lessFunc
 | 
						|
}
 | 
						|
 | 
						|
// Sort sorts the argument slice according to the less functions passed to OrderedBy.
 | 
						|
func (ms *multiSorter) Sort(changes []Change) {
 | 
						|
	ms.changes = changes
 | 
						|
	sort.Sort(ms)
 | 
						|
}
 | 
						|
 | 
						|
// OrderedBy returns a Sorter that sorts using the less functions, in order.
 | 
						|
// Call its Sort method to sort the data.
 | 
						|
func OrderedBy(less ...lessFunc) *multiSorter {
 | 
						|
	return &multiSorter{
 | 
						|
		less: less,
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Len is part of sort.Interface.
 | 
						|
func (ms *multiSorter) Len() int {
 | 
						|
	return len(ms.changes)
 | 
						|
}
 | 
						|
 | 
						|
// Swap is part of sort.Interface.
 | 
						|
func (ms *multiSorter) Swap(i, j int) {
 | 
						|
	ms.changes[i], ms.changes[j] = ms.changes[j], ms.changes[i]
 | 
						|
}
 | 
						|
 | 
						|
// Less is part of sort.Interface. It is implemented by looping along the
 | 
						|
// less functions until it finds a comparison that is either Less or
 | 
						|
// !Less. Note that it can call the less functions twice per call. We
 | 
						|
// could change the functions to return -1, 0, 1 and reduce the
 | 
						|
// number of calls for greater efficiency: an exercise for the reader.
 | 
						|
func (ms *multiSorter) Less(i, j int) bool {
 | 
						|
	p, q := &ms.changes[i], &ms.changes[j]
 | 
						|
	// Try all but the last comparison.
 | 
						|
	var k int
 | 
						|
	for k = 0; k < len(ms.less)-1; k++ {
 | 
						|
		less := ms.less[k]
 | 
						|
		switch {
 | 
						|
		case less(p, q):
 | 
						|
			// p < q, so we have a decision.
 | 
						|
			return true
 | 
						|
		case less(q, p):
 | 
						|
			// p > q, so we have a decision.
 | 
						|
			return false
 | 
						|
		}
 | 
						|
		// p == q; try the next comparison.
 | 
						|
	}
 | 
						|
	// All comparisons to here said "equal", so just return whatever
 | 
						|
	// the final comparison reports.
 | 
						|
	return ms.less[k](p, q)
 | 
						|
}
 | 
						|
 | 
						|
var changes = []Change{
 | 
						|
	{"gri", "Go", 100},
 | 
						|
	{"ken", "C", 150},
 | 
						|
	{"glenda", "Go", 200},
 | 
						|
	{"rsc", "Go", 200},
 | 
						|
	{"r", "Go", 100},
 | 
						|
	{"ken", "Go", 200},
 | 
						|
	{"dmr", "C", 100},
 | 
						|
	{"r", "C", 150},
 | 
						|
	{"gri", "Smalltalk", 80},
 | 
						|
}
 | 
						|
 | 
						|
// ExampleMultiKeys demonstrates a technique for sorting a struct type using different
 | 
						|
// sets of multiple fields in the comparison. We chain together "Less" functions, each of
 | 
						|
// which compares a single field.
 | 
						|
func Example_sortMultiKeys() {
 | 
						|
	// Closures that order the Change structure.
 | 
						|
	user := func(c1, c2 *Change) bool {
 | 
						|
		return c1.user < c2.user
 | 
						|
	}
 | 
						|
	language := func(c1, c2 *Change) bool {
 | 
						|
		return c1.language < c2.language
 | 
						|
	}
 | 
						|
	increasingLines := func(c1, c2 *Change) bool {
 | 
						|
		return c1.lines < c2.lines
 | 
						|
	}
 | 
						|
	decreasingLines := func(c1, c2 *Change) bool {
 | 
						|
		return c1.lines > c2.lines // Note: > orders downwards.
 | 
						|
	}
 | 
						|
 | 
						|
	// Simple use: Sort by user.
 | 
						|
	OrderedBy(user).Sort(changes)
 | 
						|
	fmt.Println("By user:", changes)
 | 
						|
 | 
						|
	// More examples.
 | 
						|
	OrderedBy(user, increasingLines).Sort(changes)
 | 
						|
	fmt.Println("By user,<lines:", changes)
 | 
						|
 | 
						|
	OrderedBy(user, decreasingLines).Sort(changes)
 | 
						|
	fmt.Println("By user,>lines:", changes)
 | 
						|
 | 
						|
	OrderedBy(language, increasingLines).Sort(changes)
 | 
						|
	fmt.Println("By language,<lines:", changes)
 | 
						|
 | 
						|
	OrderedBy(language, increasingLines, user).Sort(changes)
 | 
						|
	fmt.Println("By language,<lines,user:", changes)
 | 
						|
 | 
						|
	// Output:
 | 
						|
	// 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}]
 | 
						|
	// 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}]
 | 
						|
	// 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}]
 | 
						|
	// 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}]
 | 
						|
	// 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}]
 | 
						|
 | 
						|
}
 |