Sorting8:08 with Kenneth Love
Sorting lists is often required to solve a particular problem, but that changes the list! What can we do?
sorted() takes an iterable to sort and returns a new list from it. If you need to customize the sorting, pass a function in as the
key argument. There's an optional
reverse argument that will cause the results to be reversed before they're returned.
operator.itemgetter()gets items from an object that supports that operation. We use it to get keys from dicts but it has other uses too.
operator.attrgetter() gets attributes from an object.
Wait, you didn't talk about
reversed in the video!
reversed() is important but isn't all the unique or remarkable for a video right next to
sorted(reverse=True) so I left it out. But good job, you, finding it here!
reversed() takes an iterable and reverses it, returning a new iterable. This new iterable has to be turned into a list/tuple/etc to get items from it by index.
[MUSIC] 0:00 As you know, lists are mutable, 0:04 which means that we can change them in place without having to make a new list. 0:06 This is great most of the time. 0:10 It makes it really easy for us to add a new value to a list, take a value out, or 0:11 replace a value. 0:15 This isn't great though when we need to change a list for some small action. 0:17 Maybe we need a quick and easy way to get the first item from a list alphabetically, 0:21 but we don't need to change the list everywhere. 0:25 If we call sort on a list, it'll sort it in place, 0:27 which means that the list is now sorted everywhere. 0:30 Remember that rule about no side effects? 0:33 Luckily, we have a couple of ways of sorting lists without changing them. 0:35 Let's go take a look at that in WorkSpaces. 0:39 So, one of the easiest things we can get into for avoiding side effects, 0:41 is the idea of functions that return copies of our mutable stuff. 0:47 So let's go back to our bad examples idea and 0:54 we had this important_list and 0:57 it was [5, 3, 1, 2, 4,] something like that. 1:02 And we don't want to do important_list.sort, 1:07 because that's a bad idea. 1:12 That's going to sort our list in place, and we don't want that. 1:15 You know what, I'm going to leave that there, and 1:18 I'm gonna say, bad idea, sorts list in place. 1:19 And then we're gonna comment that line out cuz we don't want that line to happen. 1:22 So what do we do if we want important_list to be sorted for something, right? 1:27 We need to print the sorted version of the list, or 1:34 we need to use the sorted version of the list. 1:38 Well, Python has a handy function called sorted. 1:40 And what sorted does is it returns you a sorted copy of the list. 1:43 It doesn't sort the original list. 1:47 It takes the original list, makes a copy, sorts that copy, sends you back that copy. 1:49 So let's look at this. 1:54 Let's do print(important_list). 1:55 Actually, we don't need to print(important_list) there. 2:00 We can print(important_list) here after we print the sorted 2:05 version of important_list, just to prove that the list isn't getting sorted. 2:11 So if we do python stock.py, our sorted version here comes out as [1, 2:17 2, 3, 4, 5], as it should. 2:22 And we still get [5, 3, 1, 2, 4], just like that. 2:26 So we didn't actually change sorted, so that's good. 2:30 So I'll leave another comment here, 2:36 sorted(important_list) Sorts a copy of the list. 2:38 And we'll take those out. 2:46 Okay, but 2:47 now just using sorted on its own like that isn't the most useful thing ever. 2:48 I mean, that's cool, I can sort a list, but what if I need to sort it about 2:53 something that isn't just the natural state of the list, right? 2:57 If you look here I have a list of books, right? 3:02 Like BOOKS here is a list of books. 3:06 But if I say sort these books, it doesn't know how to sort these books. 3:07 It's probably gonna end up doing it by the repper, which is the title. 3:12 So then I get them sorted by title. 3:15 But maybe that's handy, maybe that's not. 3:17 So let's look at a couple different ways to sort different things. 3:20 So first of all, we need to go up here and we need to import a couple of things. 3:24 From operator import itemgetter, and, let's see, 3:28 I like the alphabetical things, attrgetter. 3:33 Okay, so we're gonna import attrgetter, or attribute getter, and itemgetter. 3:39 So what do these do? 3:45 These are little tiny functions that you give it an object, and 3:46 you give it a key or an attribute name, and then you say, 3:50 hey, get me this thing from this other thing and it does that for you. 3:54 So really handy, and it's awesome. 3:59 So let's do RAW_BOOKS = get_books ('books.json', and we say raw=True. 4:03 Okay, so now, I don't need this list, comment that out. 4:11 So now I have raw books and I have books, both of which are all my book objects. 4:16 So If I look at raw books, it's just a bunch of dictionaries. 4:22 It's a list of dictionaries, how do I sort that? 4:26 Well I sort that with item getter. 4:29 So let's try this. 4:31 Let's do, sorted(raw_data, 4:33 key=, and so key, let's talk about key for a second. 4:38 Key is a quarg to sorted that says, 4:42 use this thing as the key that you're going to sort by. 4:46 So I'm gonna sort by itemgetter, and I'm gonna sort this by 'publish_date'. 4:50 All right. 4:56 So we'll say this is pub_sort. 4:57 All right. 4:59 So. 5:03 Oops. 5:03 Gotta close another parentheses there. 5:05 So I should be able to print(pub_sort So ['publish_date']. 5:07 And I should be able to print the negative one here. 5:18 And those should be two different dates. 5:25 So let's try that out. 5:27 Oh, I'm sorry, I said raw_data and that should be RAW_BOOKS. 5:29 So let's try that out. 5:35 Yep, the first one was 1975 and the last one was 2011. 5:38 So cool, I was able to do that through the published date 5:42 key that each of these dictionaries had. 5:46 All right, let's do something similar. 5:48 You're probably wondering why is he commenting these out? 5:53 I'm commenting them out so they'll stay here, but 5:56 I don't want them to run cuz they're gonna take up a little bit of processing time. 5:58 So if we don't have to use up that processing time, that's even better. 6:01 So now let's do another sorted and let's do this one on books. 6:05 We're going to sort the objects, the book classes that I made. 6:09 All right, so we have books which is all of our data, and then so 6:14 let's do that with our key is going to be attrgetter. 6:19 We're going to pass in the ('number_of_pages') attribute. 6:24 So, let's call that pages_sort. 6:30 And then we can change this. 6:32 And then let's clear and then rerun that. 6:41 Oh, haha. 6:49 Look at me trying to use these like they're dictionaries 6:50 when they're actually objects. 6:54 Silly me. 6:57 Oh, and you know what, we should change this to be number_of_pages. 7:00 That's what I get for just thinking I can use code exactly as it's already written. 7:08 [LAUGH] So there we go. 7:12 The shortest one is 245 pages and the longest one is 1,141 pages. 7:13 So, two ways of sorting effectively the same group of stuff, 7:19 by whatever key we want. 7:24 So, as you've probably guessed, when we're doing itemgetter and 7:25 attrgetter, we don't have to pass in an object. 7:30 Sorted sends the object to that key. 7:32 So that's pretty cool. 7:36 Pretty handy. 7:38 One other thing that we can talk about real quick is we can do 7:39 reverse=True and 7:44 it'll flip our objects around, which is handy. 7:49 I know that was a lot to cover, congratulations on making it through. 7:54 Learning to use sorted, reversed, and the two getter functions, 7:57 itemgetter and attrgetter, really simplifies ordering lists. 8:00 In the next video we'll look at map, a handy way to transform iterables. 8:04
You need to sign up for Treehouse in order to download course files.Sign up