Adam Hopkins
Adam Hopkins

Reputation: 7102

Sorting list in python - Give priority

I have two lists, each is made up of objects having a date. I am trying to combine them and then order by date:

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

All well and good. However, if there is both an invoice object and payment object on the same day, I want the payment to be placed in the list before the invoice.

Upvotes: 1

Views: 3572

Answers (3)

ynimous
ynimous

Reputation: 5132

In addition to key=, you can also use cmp= in the sort function.

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)

Upvotes: 0

g.d.d.c
g.d.d.c

Reputation: 47988

You should be able to do something like this to get the sorting you want:

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

The idea being that, as long as the objects are distinct, you can create a sorting tuple that includes an indicator of which list the object came from. That'll make it sort by the dates first, then fall over to the 2nd field if the dates match.

Upvotes: 2

Dleep
Dleep

Reputation: 1065

Just do this instead:

combined = payments + invoices

python iterable.sort method is guaranteed to be stable. (See python docs on standar types, 5.6.4 note 9)

That means if there are 2 elements a and b on your list such that key(a) == key(b), then they'll keep their relative order (that means, if a was placed before b on the unsorted list, it'll still be like that after it's sorted).

Upvotes: 7

Related Questions