Reputation: 706
I have 2 lists, for example:
a = ['a','b','c','d','e']
b = ['c','a','dog']
I would like to sort the common elements in list b by the order of list a, to get something like this:
['a','c','dog']
I have read similar questions using sorted()
, however I cannot make it work when the lists do not contain the same elements (i.e. 'dog'
in list b
).
Upvotes: 0
Views: 137
Reputation: 908
You could use (frozen) sets. I have not timed this against other answers.
>>> a = ['a','b','c','d','e']
>>> b = ['c','a','dog']
>>> list((frozenset(a)^frozenset(b))^frozenset(a))
['a', 'c', 'dog']
Upvotes: 0
Reputation: 23394
One option is to use bisect
import bisect
from operator import itemgetter
a = ['a','b','c','d','e']
b = ['c','a','dog']
l = sorted([(x, bisect.bisect(a, x)) for x in b], key=itemgetter(1))
l = [x[0] for x in l]
print l
['a', 'c', 'dog']
Upvotes: 0
Reputation: 1125078
I'd turn a
into dictionary:
a_dict = dict((v, i) for i, v in enumerate(a))
and use float('inf')
to indicate values to be sorted at the end:
sorted(b, key=lambda v: a_dict.get(v, float('inf')))
Demo:
>>> a = ['a','b','c','d','e']
>>> b = ['c','a','dog']
>>> a_dict = dict((v, i) for i, v in enumerate(a))
>>> sorted(b, key=lambda v: a_dict.get(v, float('inf')))
['a', 'c', 'dog']
This has the advantage of speed; dict
lookups are O(1) versus list .index()
lookups having a O(n)
cost. You'll notice this more as a
and b
grow in size.
The disadvantage is that duplicate values in a
are handled differently; the dict
approach picks the last index versus .index()
picking the first.
Upvotes: 2
Reputation: 251186
>>> a = ['a','b','c','d','e']
>>> b = ['c','a','dog']
>>> def func(x):
... try:
... return a.index(x)
... except ValueError:
... return float("inf")
...
>>> sorted(b, key = func)
['a', 'c', 'dog']
Upvotes: 4