forked from mmcgrana/gobyexample
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsorting-by-functions
183 lines (145 loc) · 8.04 KB
/
sorting-by-functions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Go by Example: Sorting by Functions</title>
<link rel=stylesheet href="site.css">
</head>
<script>
onkeydown = (e) => {
if (e.key == "ArrowLeft") {
window.location.href = 'sorting';
}
if (e.key == "ArrowRight") {
window.location.href = 'panic';
}
}
</script>
<body>
<div class="example" id="sorting-by-functions">
<h2><a href="./">Go by Example</a>: Sorting by Functions</h2>
<table>
<tr>
<td class="docs">
<p>Sometimes we’ll want to sort a collection by something
other than its natural order. For example, suppose we
wanted to sort strings by their length instead of
alphabetically. Here’s an example of custom sorts
in Go.</p>
</td>
<td class="code empty leading">
</td>
</tr>
<tr>
<td class="docs">
</td>
<td class="code leading">
<a href="http://play.golang.org/p/h4g4vaLBtkw"><img title="Run code" src="play.png" class="run" /></a><img title="Copy code" src="clipboard.png" class="copy" />
<pre class="chroma"><span class="kn">package</span> <span class="nx">main</span>
</pre>
</td>
</tr>
<tr>
<td class="docs">
</td>
<td class="code leading">
<pre class="chroma"><span class="kn">import</span> <span class="p">(</span>
<span class="s">"fmt"</span>
<span class="s">"sort"</span>
<span class="p">)</span>
</pre>
</td>
</tr>
<tr>
<td class="docs">
<p>In order to sort by a custom function in Go, we need a
corresponding type. Here we’ve created a <code>byLength</code>
type that is just an alias for the builtin <code>[]string</code>
type.</p>
</td>
<td class="code leading">
<pre class="chroma">
<span class="kd">type</span> <span class="nx">byLength</span> <span class="p">[]</span><span class="kt">string</span>
</pre>
</td>
</tr>
<tr>
<td class="docs">
<p>We implement <code>sort.Interface</code> - <code>Len</code>, <code>Less</code>, and
<code>Swap</code> - on our type so we can use the <code>sort</code> package’s
generic <code>Sort</code> function. <code>Len</code> and <code>Swap</code>
will usually be similar across types and <code>Less</code> will
hold the actual custom sorting logic. In our case we
want to sort in order of increasing string length, so
we use <code>len(s[i])</code> and <code>len(s[j])</code> here.</p>
</td>
<td class="code leading">
<pre class="chroma">
<span class="kd">func</span> <span class="p">(</span><span class="nx">s</span> <span class="nx">byLength</span><span class="p">)</span> <span class="nf">Len</span><span class="p">()</span> <span class="kt">int</span> <span class="p">{</span>
<span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="nx">s</span><span class="p">)</span>
<span class="p">}</span>
<span class="kd">func</span> <span class="p">(</span><span class="nx">s</span> <span class="nx">byLength</span><span class="p">)</span> <span class="nf">Swap</span><span class="p">(</span><span class="nx">i</span><span class="p">,</span> <span class="nx">j</span> <span class="kt">int</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">s</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span> <span class="nx">s</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span> <span class="p">=</span> <span class="nx">s</span><span class="p">[</span><span class="nx">j</span><span class="p">],</span> <span class="nx">s</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span>
<span class="p">}</span>
<span class="kd">func</span> <span class="p">(</span><span class="nx">s</span> <span class="nx">byLength</span><span class="p">)</span> <span class="nf">Less</span><span class="p">(</span><span class="nx">i</span><span class="p">,</span> <span class="nx">j</span> <span class="kt">int</span><span class="p">)</span> <span class="kt">bool</span> <span class="p">{</span>
<span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="nx">s</span><span class="p">[</span><span class="nx">i</span><span class="p">])</span> <span class="p"><</span> <span class="nb">len</span><span class="p">(</span><span class="nx">s</span><span class="p">[</span><span class="nx">j</span><span class="p">])</span>
<span class="p">}</span>
</pre>
</td>
</tr>
<tr>
<td class="docs">
<p>With all of this in place, we can now implement our
custom sort by converting the original <code>fruits</code> slice
to <code>byLength</code>, and then use <code>sort.Sort</code> on that typed
slice.</p>
</td>
<td class="code">
<pre class="chroma">
<span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">fruits</span> <span class="o">:=</span> <span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="s">"peach"</span><span class="p">,</span> <span class="s">"banana"</span><span class="p">,</span> <span class="s">"kiwi"</span><span class="p">}</span>
<span class="nx">sort</span><span class="p">.</span><span class="nf">Sort</span><span class="p">(</span><span class="nf">byLength</span><span class="p">(</span><span class="nx">fruits</span><span class="p">))</span>
<span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">fruits</span><span class="p">)</span>
<span class="p">}</span>
</pre>
</td>
</tr>
</table>
<table>
<tr>
<td class="docs">
<p>Running our program shows a list sorted by string
length, as desired.</p>
</td>
<td class="code leading">
<pre class="chroma">
<span class="gp">$</span> go run sorting-by-functions.go
<span class="go">[kiwi peach banana]</span></pre>
</td>
</tr>
<tr>
<td class="docs">
<p>By following this same pattern of creating a custom
type, implementing the three <code>Interface</code> methods on that
type, and then calling sort.Sort on a collection of that
custom type, we can sort Go slices by arbitrary
functions.</p>
</td>
<td class="code empty">
</td>
</tr>
</table>
<p class="next">
Next example: <a href="panic">Panic</a>.
</p>
<p class="footer">
by <a href="https://markmcgranaghan.com">Mark McGranaghan</a> and <a href="https://eli.thegreenplace.net">Eli Bendersky</a> | <a href="https://github.com/mmcgrana/gobyexample">source</a> | <a href="https://github.com/mmcgrana/gobyexample#license">license</a>
</p>
</div>
<script>
var codeLines = [];
codeLines.push('');codeLines.push('package main\u000A');codeLines.push('import (\u000A \"fmt\"\u000A \"sort\"\u000A)\u000A');codeLines.push('type byLength []string\u000A');codeLines.push('func (s byLength) Len() int {\u000A return len(s)\u000A}\u000Afunc (s byLength) Swap(i, j int) {\u000A s[i], s[j] \u003D s[j], s[i]\u000A}\u000Afunc (s byLength) Less(i, j int) bool {\u000A return len(s[i]) \u003C len(s[j])\u000A}\u000A');codeLines.push('func main() {\u000A fruits :\u003D []string{\"peach\", \"banana\", \"kiwi\"}\u000A sort.Sort(byLength(fruits))\u000A fmt.Println(fruits)\u000A}\u000A');codeLines.push('');codeLines.push('');
</script>
<script src="site.js" async></script>
</body>
</html>