2015-12-02 107 views
0

我有两个列表,每个列表由date对象组成。我试图结合他们,然后按日期排序:python排序列表 - 给予优先

combined = invoices + payments 
combined.sort(key = lambda x: x.date) 

一切顺利,好。但是,如果在同一天同时有invoice对象和payment对象,我希望将payment放置在invoice之前的列表中。

回答

6

只是这样做,而不是:

combined = payments + invoices 

蟒蛇iterable.sort方法是保证稳定。 (See python docs on standar types, 5.6.4 note 9

这意味着,如果有2个元素ab您的列表,使得key(a) == key(b),那么他们会继续它们的相对顺序(也就是说,如果ab之前放置在无序列表,它会在排序后仍然如此)。

+0

我正在寻找一些信息,就像那张纸条一样。感谢您的参考。我找不到。解决方案太简单了。不能相信我错过了这个明显的。 –

+0

顺便说一句,假设你有is_invoice布尔属性,那么你已经混合了数据,你可以用'combined.sort(key = lambda x:(x.date,x.is_invoice))'对它们进行排序。一个元组将被逐项执行,所以如果第一个项目(日期)相同,则第二个(is_invoice)将被比较(并且False将在True之前)。 – zvone

2

你应该能够做到像这样得到的排序,你想:

combined.sort(key = lambda x: (x.date, 1 if x in invoices else 0)) 

的想法是,只要对象是不同的,你可以创建一个排序元组包含一个指标其中的对象来自哪个列表。这将首先按日期进行排序,然后如果日期匹配,则会倒退到第二个字段。

+0

这是很好的信息,我很肯定这个想法。我认为我有另一个使用这种逻辑的好地方。 –

0

除了key=,您还可以在sort函数中使用cmp=

class Invoice(object): 
    P = 1 
    def __init__(self, date): 
     self.date = date 

class Payment(object): 
    P = 0 
    def __init__(self, date): 
     self.date = date 


l = [Invoice(10), Payment(10), Invoice(10)] 

def xcmp(x, y): 
    c0 = cmp(x.date, y.date) 
    return c0 if c0 != 0 else cmp(x.__class__.P, y.__class__.P) 

l.sort(cmp=xcmp)