volingas
volingas

Reputation: 1173

Sort a list of objects according to a property in another list

My data consists of objects with some property (pk):

obj0.pk = 'aa'
obj1.pk = 33
ojb2.pk = 'm0'

I have a bunch of unordered objects:

data = [obj0, obj1, obj2]

And I have the list of pks which specify how to order the objects:

pks = [33, 'aa', 'm0']

Now I call a function to order the data:

output = sort_data_by_pk(data, pks)

Expected output:

[obj1, obj0, obj2]

How can we implement sort_data_by_pk in python?

EDIT

My initial implementation is:

def sort_data_by_pk(data, pks):
    lookup = {instance.pk: instance for instance in data}
    return [lookup[pk] for pk in pks]

Upvotes: 0

Views: 51

Answers (4)

Reductio
Reductio

Reputation: 539

If your lists are big, you might want to create a dict first, to avoid multiple calls of "index" on the list.

pks = [33, 'aa', 'm0']
data = [ob0, ob1, ob2]
d = { obj.pk: obj for obj in data } #lookup table for pks
sorted_list = [ d[pk] for pk in pks ] #create a new list out of list "pks" where pk is replaced by the value in the lookup table

Upvotes: 2

blhsing
blhsing

Reputation: 107124

Using the index method as a key function unnecessarily makes the solution O(n^2 log n) rather than O(n log n) in average time complexity.

Instead, you can build a dict that maps the items in data to their indices, so that you can use the dict to map the objects' pk attribute as a key function for sort order:

order = {k: i for i, k in enumerate(pks)}
output = sorted(data, key=lambda o: order[o.pk])

Upvotes: 3

wpercy
wpercy

Reputation: 10090

I think you want to use sorted with a lambda that gets the index of the primary key in pks.

sorted_data = sorted(data, lambda d: pks.index(d.pk))

Upvotes: 2

han solo
han solo

Reputation: 6600

You could sort data based on the index in the pks like,

>>> pks = [33, 'aa', 'm0']
>>> data = [ob0, ob1, ob2]
>>> 
>>> 
>>> sorted(data, key=lambda x: pks.index(x.pk))
[<__main__.Obj object at 0x7f03851cc290>, <__main__.Obj object at 0x7f03851cc250>, <__main__.Obj object at 0x7f03851cc2d0>]

Upvotes: 2

Related Questions