4

I am working with Python list sort.

I have two lists: one is a list of integers, the other is a list of objects, and the second object list has the attribute id which is also an integer, I want to sort the object list based on the id attribute, in the order of the same id appears in the first list, well, this is an example:

I got a = [1,2,3,4,5]

and b = [o,p,q,r,s], where o.id = 2, p.id = 1, q.id = 3, r.id = 5, s.id = 4

and I want my list b to be sorted in the order of its id appears in list a, which is like this:

sorted_b = [p, o, q, s, r]

Of course, I can achieve this by using nested loops:

sorted_b = []
for i in a:
    for j in b:
        if j.id == i:
            sorted_b.append(j)
            break

but this is a classic ugly and non-Python way to solve a problem, I wonder if there is a way to solve this in a rather neat way, like using the sort method, but I don't know how.

4 Answers 4

8
>>> from collections import namedtuple
>>> Foo = namedtuple('Foo', 'name id') # this represents your class with id attribute
>>> a = [1,2,3,4,5]
>>> b = [Foo(name='o', id=2), Foo(name='p', id=1), Foo(name='q', id=3), Foo(name='r', id=5), Foo(name='s', id=4)]
>>> sorted(b, key=lambda x: a.index(x.id))
[Foo(name='p', id=1), Foo(name='o', id=2), Foo(name='q', id=3), Foo(name='s', id=4), Foo(name='r', id=5)]
Sign up to request clarification or add additional context in comments.

Comments

2

This is a simple way to do it:

# Create a dictionary that maps from an ID to the corresponding object
object_by_id = dict((x.id, x) for x in b)

sorted_b = [object_by_id[i] for i in a]

If the list gets big, it's probably the fastest way, too.

1 Comment

Cool! I like your way to tackle with this problem, many thanks!
1

You can do it with a list comprehension, but in general is it the same.

sorted_b = [ y for x in a for y in b if y.id == x ]

1 Comment

I think jamylak's answer is what I'm looking for, but thanks anyway:)
0

There is a sorted function in Python. It takes optional keyword argument cmp. You can pass there your customized function for sorting.

cmp definition from the docs:

custom comparison should return a negative, zero or positive number depending on whether the first argument is considered smaller than, equal to, or larger than the second argument

a = [1,2,3,4,5]
def compare(el1, el2):
   if a.index(el1.id) < a.index(el2.id): return -1
   if a.index(el1.id) > a.index(el2.id): return 1
   return 0

sorted(b, cmp=compare)

This is more straightforward however I would encourage you to use the key argument as jamylak described in his answer, because it's more pythonic and in Python 3 the cmp is not longer supported.

2 Comments

But I got a little bit confused with the two if statements in the compare function, can you explain that to me? I'm not familiar with the cmp argument, thanks.
Then I think the second if statement should be if a.index(el1.id) > a.index(el2.id). Now I got it, thank you fellow.

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.