2011-11-03 106 views
6

我有一系列的名单,看起来像这样:在Python中使用自定义排序参数排序列表的最佳方式是什么?

li1 = ['a.1', 'b.9', 'c.8', 'd.1', 'e.2'] 
li2 = ['a.4', 'b.1', 'c.2', 'd.2', 'e.4'] 

我如何重新安排在每个列表中,这样的第一个项目是“b.something”的项目?对于上面的示例:

li1 = ['b.9', 'a.1', 'c.8', 'd.1', 'e.2'] 
li2 = ['b.1', 'a.4', 'c.2', 'd.2', 'e.4'] 

在第一项不重要后维护订单。谢谢您的帮助。

+0

我不确定,但是这个问题可能会对你感兴趣:http://stackoverflow.com/questions/2436607/how-to-use-re-match-objects-in-a-list-comprehension –

+0

只是想知道为什么每个人都用's.startwith('b')',而不是'[0] =='b''。有没有什么性能优势?如果不是,我想保存我的大脑的长期记忆使用。 – yosukesabai

+0

@yosukesabai:只有一个答案使用's.startwith('b')'。其他人使用's.startwith('b。')'就像在问题中要求的那样。 –

回答

4

重新排列项目中的每个列表中,这样的第一个项目是“b.something”

维护订单后的第一项是不重要的。

那是不排序,然后。从概念上讲,你只是想把这个元素放在前面。

换句话说,您需要一个由该元素组成的列表,后面跟着不是该元素的所有元素。对于存在多个b.something s的情况稍加修改,注意我们不关心发生了什么,只要第一个元素是b.something,我们可以重新说明:满足条件的每个元素的列表(“开始与b.“),其次是每个不符合条件的元素。 (这有时被称为分区;参见例如std::partition在C++)

在Python,这是为描述这两个列表的组件与列表解析和粘在一起它们作为简单:

[x for x in li if x.startswith('b.')] + [x for x in li if not x.startswith('b.')] 

......或者你可以假装你正在排序,只是在应用了key之后,只有一些元素只有两个值,并应用相应的key,如Ignacio Vasquez-Abrams的回答。

+0

这是最接近请求。无论如何,我不知道“排序”的速度有多快,因为您必须使用相同的函数来读取列表两次以进行过滤。 –

+0

哇,这很酷。出于某种原因,加入列表解析一起从未发生过。谢谢。 – drbunsen

+0

@Joël两次读取列表只会导致恒定因子开销。排序是O(n lg n),因为'sort'需要能够任意排序,因此必须做某种基于比较的排序,而每个过滤列表理解过程通常被看作O(n)。 –

3

您可以使用sorted,接受一个key参数,并返回一个列表:

>>> li1 = ['a.1', 'b.2', 'c.8'] 
>>> def k(s): 
...  if s.startswith('b.'): 
...   return 1 
...  else: 
...   return 2 
... 
>>> sorted(li1, key=k) 
['b.2', 'a.1', 'c.8'] 

k应返回的东西,可以迭代项目之间进行比较。

注意:sort更改输入就地并不返回任何内容,当sorted返回排序列表并且不修改您的列表。两者都以相同的方式工作。

5

Python的排序是稳定的,所以你会保持第一个项目后的顺序无论。

li1.sort(key=lambda x: not x.startswith('b.')) 
+1

这非常漂亮,但我想有些人会认为“显式比隐式更好”意味着您不应该将布尔值视为可比较的值(“False

相关问题