Reputation: 55
So, I have two lists which contain:
[10, 10, 2, 9, 10]
['Jem', 'Sam', 'Sam', 'Jem', 'Jem']
I want to sort the second list using the .sort() function, and I want the changes made to the second list to affect the first list, i.e.
['Jem', 'Jem', 'Jem', 'Sam', 'Sam']
[10, 9, 10, 10, 2]
If that wasn't clear, then think of it as the two lists being linked. The strings/integers at each point in the two lists ([0], [1] etc.) are joined together, so that every change to the position of an element of one list is reflected by an equal change in the position of the corresponding element in the other list. How would I achieve this?
Upvotes: 1
Views: 217
Reputation: 16711
Just zip
them together and sort by name:
name = ['Jem', 'Sam', 'Sam', 'Jem', 'Jem']
nums = [10, 10, 2, 9, 10]
sort = sorted(zip(name, nums), key = lambda i:i[0])
name = [i[0] for i in sort] # split name again
nums = [i[1] for i in sort] # split nums again
Upvotes: 0
Reputation: 1671
It's about time you were introduced to Python's zip!
And then you could use it like this:
def sorted_together(*args, **kwargs):
reverse = False
key = None
if 'reverse' in kwargs:
reverse = kwargs['reverse']
if 'key' in kwargs:
key = kwargs['key']
zipped = zip(*args)
zipped.sort(reverse=reverse, key=key)
tups = zip(*zipped)
lists = [list(x) for x in tups] #
return lists
Remember that zip() returns a list of tuples, so if you're looking to get lists back out at the end the last list comprehension is very necessary.
Upvotes: 1
Reputation: 500207
Here is one way to do it:
In [18]: l1 = [10, 10, 2, 9, 10]
In [19]: l2 = ['Jem', 'Sam', 'Sam', 'Jem', 'Jem']
In [20]: l2, _, l1 = map(list, zip(*sorted(zip(l2, range(len(l1)), l1))))
In [21]: l1
Out[21]: [10, 9, 10, 10, 2]
In [22]: l2
Out[22]: ['Jem', 'Jem', 'Jem', 'Sam', 'Sam']
From the inside out:
zip(l2, range(len(l1)), l1)
produces a list of tuples like so:
[('Jem', 0, 10), ('Jem', 1, 9), ('Jem', 2, 10), ('Sam', 3, 10), ('Sam', 4, 2)]
Here, the first element is the item from l2
, the second element is simply a counter starting from zero, and the third element is the item from l1
.
sorted(...)
sorts the tuples first by l2
and then by the position in the original list (I am guessing from your example that this is what you want; the code can be simplified if you have no such requirement).
zip(*...)
splits the sorted list into a list of three tuples.
map(list, ...)
converts the tuples to lists.
l2, _, l1
assigns the first and third lists to l2
and l1
, and discards the second list.
Upvotes: 1
Reputation: 117856
If the lists are indeed correlated/related, I would zip
them.
>>> l1 = [10, 10, 2, 9, 10]
>>> l2 = ['Jem', 'Sam', 'Sam', 'Jem', 'Jem']
>>> pairs = list(zip(l1,l2))
>>> pairs
[(10, 'Jem'), (10, 'Sam'), (2, 'Sam'), (9, 'Jem'), (10, 'Jem')]
Then you can sort them by the names or the values using the key
argument of sort
or sorted
>>> sorted(pairs, key = lambda i : i[1])
[(10, 'Jem'), (9, 'Jem'), (10, 'Jem'), (10, 'Sam'), (2, 'Sam')]
Upvotes: 1
Reputation: 50540
It may make sense to actually link your two lists into a list of tuples:
list_1 = [10, 10, 2, 9, 10]
list_2 = ['Jem', 'Sam', 'Sam', 'Jem', 'Jem']
merged_list = zip(list_1, list_2)
print sorted(merged_list, key=lambda x: x[1])
This prints out the following:
[(10, 'Jem'), (9, 'Jem'), (10, 'Jem'), (10, 'Sam'), (2, 'Sam')]
You can then unmerge these lists (into two separate tuples) if you need, otherwise you can operate on the list of tuples
unlinked = zip(*sorted_merged)
print unlinked
Outputs:
[(10, 9, 10, 10, 2), ('Jem', 'Jem', 'Jem', 'Sam', 'Sam')]
Upvotes: 1