Python sort list customisation
2016-04-11 22:25
405 查看
Sorting a Python List the Simple Way
Okay, so if you only want to sort a list of numbers, Python has a built in function that does all the hard work for you.Say we have a list of numbers:
1 | >>>a=[3,6,8,2,78,1,23,45,9] |
sorton the list, for in-place sorting, or the built in function
sortedfor
not modifying the original list and returning a new sorted list. Both functions take in the same arguments and can be treated as "the same" for our purposes here, except for the reason above.
Here we go:
1 2 3 4 5 6 | >>>sorted(a) [1,2,3,6,8,9,23,45,78] >>> >>>a.sort() >>>a [1,2,3,6,8,9,23,45,78] |
Here you go:
1 2 3 4 5 | >>>sorted(a,reverse=True) [78,45,23,9,8,6,3,2,1] >>>a.sort(reverse=True) >>>l [78,45,23,9,8,6,3,2,1] |
__cmp__on each object
when comparing values, and decides which one to put in front of the other based on the value returned from
__cmp__. The return value
is
0for equal to,
1for
greater than, and
-1for less than the compared value. We'll use this information later to make our own objects sortable.
What about tuples, you say? I'm getting to that.
Sorting a Python Tuple the Simple Way
Since tuples are arrays that you cannot modify, they don't have an in-place sortfunction that can be called directly on them. They
must always use the
sortedfunction to return a sorted list. Keeping that in mind, here's how to do it:
1 2 3 | >>>tup=(3,6,8,2,78,1,23,45,9) >>>sorted(tup) [1,2,3,6,8,9,23,45,78] |
sortedreturns an array.
Okay, now let's see how to sort something a little more complicated.
Sorting a List of Lists or Tuples
This is a little more complicated, but still pretty easy, so don't fret! Both the sortedfunction and the
sortfunction
take in a keyword argument called
key.
What
keydoes is it provides a way to specify a function that returns what you would like your items sorted by. The function gets
an "invisible" argument passed to it that represents an item in the list, and returns a value that you would like to be the item's "key" for sorting.
Let me illustrate, for your superb eyes only, the
keykeyword argument!
So, taking a new list, let's test it out by sorting by the first item in each sub-list:
1 2 3 4 5 | >>>defgetKey(item): ... returnitem[0] >>>l=[[2,3],[6,7],[3,34],[24,64],[1,43]] >>>sorted(l,key=getKey) [[1,43],[2,3],[3,34],[6,7],[24,64]] |
sortfunction
as well, but I personally like the
sortedfunction better, so I'll be using that in further examples.
What happened? Remember that "invisible" argument I was talking about? That's what gets passed into the
getKeyfunction every time
the
sortedneeds a value. Tricky, tricky python ;).
Sorting by the second item in each sub-list would be as simple as changing the
getKeyfunction to this:
1 2 | defgetKey(item): returnitem[1] |
It's actually the exact same as our example above, but has the list defined as such:
1 2 3 | >>>a=[(2,3),(6,7),(3,34),(24,64),(1,43)] >>>sorted(l,key=getKey) [(1,43),(2,3),(3,34),(6,7),(24,64)] |
The exact same solution can be applied to a tuple of tuples, so I'm not going to go there, as that would just be redundant. It would also waste more of those digital trees that make this beautiful digital paper.
Sorting a List (or Tuple) of Custom Python Objects
Here's a custom object that I created:1 2 3 4 | classCustom(object): def__init__(self,name,number): self.name=name self.number=number |
1 2 3 4 5 6 | customlist=[ Custom('object',99), Custom('michael',1), Custom('theodore the great',59), Custom('life',42) ] |
Well, we could define a function, like we did above, that takes in the item and returns a list. So let's do that.
1 2 | defgetKey(custom): returncustom.number |
numberproperty in the custom
object.
So if we run the
sortedfunction on our list of fancy custom objects, we get this:
1 2 3 4 5 | >>>sorted(customlist,key=getKey) [<__main__.Customobjectat0x7f64660cdfd0>, <__main__.Customobjectat0x7f64660d5050>, <__main__.Customobjectat0x7f64660d5090>, <__main__.Customobjectat0x7f64660d50d0>] |
Let's redefine our object class like this:
1 2 3 4 5 6 7 8 9 | classCustom(object): def__init__(self,name,number): self.name=name self.number=number def__repr__(self): return'{}: {} {}'.format(self.__class__.__name__, self.name, self.number) |
__repr__function tells Python how we want the object to be represented as. In more
complex terms, it tells the interpreter how to display the object when it is printed to the screen.
So, we tell Python to represent the object by it's class name, name, and number.
Now lets try sorting it again:
1 2 3 | >>>sorted(customlist,key=getKey) [Custom:michael1,Custom:life42, Custom:theodorethegreat59,Custom:object99] |
But there's a little bit of a problem. It's just nit-picking, but I don't want to have to type that
keykeyword every time I call
sorted.
So, how do I do that? Well, remember that
__cmp__function I told you about? Let's put it into action!
Let's redefine our object one more time like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 | classCustom(object): def__init__(self,name,number): self.name=name self.number=number def__repr__(self): return'{}: {} {}'.format(self.__class__.__name__, self.name, self.number) def__cmp__(self,other): ifhasattr(other,'number'): returnself.number.__cmp__(other.number) |
sortedfunction
will call the
__cmp__function on the objects it is sorting in order to determine where they should be in relation to other objects.
Now we can just call
sortedwithout worrying about including the
keykeyword,
like so:
1 2 | >>>sorted(customlist) [Custom:michael1,Custom:life42,Custom:theodorethegreat59,Custom:object99] |
Sorting a Heterogeneous List of Custom Python Objects
Alright. Since Python is a dynamic language, it doesn't so much care about what objects we throw into lists. They can all be the same type, or they can all be different.So let's define another different object to use with our
Customobject.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | classAnotherObject(object): def__init__(self,tag,age,rate): self.tag=tag self.age=age self.rate=rate def__repr__(self): return'{}: {} {} {}'.format(self.__class__.__name__, self.tag, self.age,self.rate) def__cmp__(self,other): ifhasattr(other,'age'): returnself.age.__cmp__(other.age) |
Customobject.
Let's make a list of these and our
Customobjects:
1 2 3 4 5 6 7 8 9 | customlist=[ Custom('object',99), Custom('michael',1), Custom('theodore the great',59), Custom('life',42), AnotherObject('bananas',37,2.2), AnotherObject('pants',73,5.6), AnotherObject('lemur',44,9.2) ] |
sortedon this list:
1 2 3 4 | >>>sorted(customlist) Traceback(mostrecentcalllast): File"<stdin>",line1,in<module> TypeError:anintegerisrequired |
Customdoesn't have an attribute called
ageand
AnotherObjectdoesn't
have an attribute called
number.
What do we do? Panic!
Just kidding. We know what to do. Let's redefine those objects again!
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 | classCustom(object): def__init__(self,name,number): self.name=name self.number=number def__repr__(self): return'{}: {} {}'.format(self.__class__.__name__, self.name, self.number) def__cmp__(self,other): ifhasattr(other,'getKey'): returnself.getKey().__cmp__(other.getKey()) defgetKey(self): returnself.number classAnotherObject(object): def__init__(self,tag,age,rate): self.tag=tag self.age=age self.rate=rate def__repr__(self): return'{}: {} {} {}'.format(self.__class__.__name__, self.tag, self.age,self.rate) def__cmp__(self,other): ifhasattr(other,'getKey'): returnself.getKey().__cmp__(other.getKey()) defgetKey(self): returnself.age |
getKeyfunction that both of the objects have so that we can compare them easily.
So now if we run the
sortedfunction again, we get:
1 2 3 4 5 | >>>sorted(customlist) [Custom:michael1,AnotherObject:bananas372.2, Custom:life42,AnotherObject:lemur449.2, Custom:theodorethegreat59,AnotherObject:pants735.6, Custom:object99] |
You still prefer the using the
keykeyword, you say?
You can do that too. If you leave out the
__cmp__functions in each object, and define an outside function like so:
1 2 | defgetKey(customobj): returncustomobj.getKey() |
1 2 3 4 5 | >>>sorted(customlist,key=getKey) [Custom:michael1,AnotherObject:bananas372.2, Custom:life42,AnotherObject:lemur449.2, Custom:theodorethegreat59,AnotherObject:pants735.6, Custom:object99] |
sortedfunction.
For more sorting ideas, head over to How
to Sort Python Dictionaries by Key or Value. You could also check out Lambda
Function Syntax (Inline Functions) in Python for instructions on how to sort with lambda functions.
And there you are. One step closer to becoming the world's Python master.
相关文章推荐
- Python 生成器 generator之next和send运行流程
- Python金融应用编程(数据分析、定价与量化投资)
- Python金融应用编程(数据分析、定价与量化投资)
- 使用python抓取婚恋网用户数据并用决策树生成自己择偶观
- Python 如何安装各种模块(1)
- python模块
- python伪装浏览器爬虫
- Python+PyQt4+Eric6合并Excel的图形化界面设计
- windows下python安装Numpy、matplotlib和whl文件
- Python
- python 的拷贝、深度拷贝及内存管理
- python 下载文件汇总
- python浓缩(7)映射和集合类型
- python学习9-语句
- python笔记 - 高级属性(20160411)
- Python2.7 smtplib发送带附件邮件报错STARTTLS解决方法
- Python2.7 smtplib发送带附件邮件报错STARTTLS解决方法 推荐
- python 模拟登录
- 机器学习/数据挖掘学习资源
- python命令行自动补全