1

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.

0

3 Answers 3

7

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).

Sign up to request clarification or add additional context in comments.

2 Comments

I was hunting for some information just like that note. Thanks for the reference. I could not find it. The solution was just too simple. Cannot believe I missed the obvious.
BTW, it you had mixed data, you could sort them with combined.sort(key = lambda x: (x.date, x.is_invoice)), assuming you have is_invoice boolean property. A tuple will be compered item by item, so if the first item (date) is the same, the second (is_invoice) will be compared (and False will be before True).
2

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.

1 Comment

That is good information, I like the idea for sure. I think I have another good place to use this same sort of logic.
0

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)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.