There are numerous ways to sort slices in Go.
In this lesson, we will take a quick look at an easy way to sort a slice of structs or primitives. We will learn about using one of the handy built-in functions in Go's sort package called sort.Slice. This function takes a slice to sort as an argument and a less function or less func for short as the second argument. You will write this less function to sort the slice however you wish.
Go's sort.Slice function looks like this: sort.Slice(someSlice, func(i, j int) bool). It's super-easy to write an anonymous less function to sort.
As you will see, it's easy to use this less function to do simple and even complex sorts of your structs with minimal effort.
Instructor: [00:00] In this lesson, we're going to learn about sorting structs. To do that, I'm going to show you about another built-in function in Go's sort package called Slice. It's sort.Slice. Let's start off by loading some champions into a slice and printing them out.
[00:19] I'm going to trim the champions only down to the first 10 to cut down on the amount of data that I'm working with. To see what we have here, we have a JSON structure in a file that I'm loading.
[00:34] Each JSON element is a Teamfight Tactics champion, containing a name, some classes, some origins, and a goal cost. Those get loaded into this Champion's struct that has fields that correspond to the JSON data.
[00:50] Let me go ahead and run this and we'll see what we have. I just printed out the first 10 so we can see what we're working with. The first 10 champs floated from the file look like this. Let's sort this data using the sort.slice function. Again, this is a built-in function. You have to add sort up here to import it.
[01:16] Let's take a look at this. The sort.slice function takes a slice of structs and it could be anything. It can actually be Ints, any primitives, any structs, any type of slice. Also, a function that takes two indexes, I and J, or whatever you want to call them. This function is called a less function. It is used to compare the data to sort it.
[01:45] In this case, the function will take the champion at index I and extract the name, and answer a Boolean whether or not that name is less than the name of the champion at index J.
[02:06] This is a very simple sort comparator function that just returns whether or not the name of one champ is less than the name of another champ. It uses this actually to sort the data. The next line, here at 22, is going to print out the sorted slice. Let me run that.
[02:27] If you look here, this is the unsorted slice, and it sorted the elements in the slice by name. We have a tructs first followed by a cali, and you can see Z here at the end. We were able to use the sort.slice function to do a simple sorting of structs.
[02:53] What is this thing exactly? What is this less function that we have to implement here in order to compare? This borders on maybe out of the scope of this lesson, but I'm going to try and explain what's going on here a little better. Under the covers, go is performing some sort of sorting algorithm.
[03:11] For the sake of discussion, let's assume it's a bubble sort. What happens here is that if we look at the unsorted data, the way a bubble sort works is the algorithm takes the first and second elements in the collection and compares them. What it does is it's going to call our less function.
[03:37] If the less function returns true, then nothing happens. If it returns false, then the algorithm is going to swap these two elements. In this case, Evelyn is not less than a cali, so nothing happens. Then the algorithm moves on to the next two adjacent elements, that being Evelyn and Katarina.
[04:00] Again, the less function is called with index one and two. The less function compares those names, that answer's true, so nothing happens. This will continue on until the less function returns false, in which case the algorithm will swap the elements at indexes I and J.
[04:25] It will continue that until it reaches the end of the slice. Then, it will start over and go through the entire slice again doing the same thing, calling the less function for every single one until it is able to complete the entire pass through the collection without swapping anything.
[04:47] At that point, the collection is sorted, and the sort process ends. Since we're able to specify the comparator, which is this function again, we can change the sort order to be descending instead of ascending.
[05:04] All we have to do, in this example here, I do the exact same thing except I flip, and I say champs.i.name>champs.j.name. I could've written that another way by flipping the j in front of the i, but either way, it works the same. Then, I'll print that out.
[05:21] Let's take a look. We can see that now we were able to use that comparator -- the less function -- to sort descending by name. You can see Z is first and Atrox is last.
[05:40] Next up, I'm going to use the sort.slice function to sort in ascending order buy gold cost. Again, it's just a simple less function that extracts the cost from each champ and compares those.
[05:54] I'm going to print that out. We can see that now the slice of champions is sorted by gold cost. All of the ones are together followed by the twos, threes and fours at the end.
[06:13] The last thing I want to show you is how we can use the less function -- this comparator -- to do more complex things. In this example, I'm going to sort the champions by multiple criteria. First, by descending gold cost so the most expensive champions are first and then for those that are equal in the same gold cost, then I'm going to sort by name.
[06:38] I just have a little bit more complicated less function which first checks the gold cost and if the gold cost is greater than, then it simply returns true. Otherwise, if the cost is less than, it returns false. If the cost is equal, then it falls back to the name comparison in ascending name order. Let's run this and we'll see what we get.
[07:06] As you would expect, we sort by cost first in descending order so the most expensive champions are listed first. For those that have the same gold cost like, Callie and Draven, they both cost four their listed in alphabetical order by name.
[07:27] This repeats itself followed by all the threes, Atrox, Evelyn and Katarina and also Ringer then the twos and the ones at the end. As you can see, the sort.slice function is very powerful with minimal effort.