# sorting two corresponding lists?

Discussion in 'Python' started by Esmail, Apr 20, 2009.

1. ### EsmailGuest

Hello all,

I wonder if someone could help me with sorting two corresponding lists.

For instance the first list contains some items, and the second list
contains their value (higher is better)

items = [apple, car, town, phone]
values = [5, 2, 7, 1]

I would like to sort the 'items' list based on the 'values' list so
that I end up with the following two list:

items = [town, apple, car, phone]
values = [7, 5, 2, 1]

So I would like to keep the corresponding value still corresponding
after the sorting.

Is there an easy/nice/Pythonic way to do this?

Thanks,
Esmail

Esmail, Apr 20, 2009

2. ### Diez B. RoggischGuest

Esmail wrote:

> Hello all,
>
> I wonder if someone could help me with sorting two corresponding lists.
>
> For instance the first list contains some items, and the second list
> contains their value (higher is better)
>
> items = [apple, car, town, phone]
> values = [5, 2, 7, 1]
>
> I would like to sort the 'items' list based on the 'values' list so
> that I end up with the following two list:
>
> items = [town, apple, car, phone]
> values = [7, 5, 2, 1]
>
> So I would like to keep the corresponding value still corresponding
> after the sorting.
>
> Is there an easy/nice/Pythonic way to do this?

items = zip(*sorted(zip(values, items)))[1]

To better understand this please note that

a = [1, 2]
b = [3, 4]

zip(*zip(a, b)) == a, b

or, in other words, zip(*argument) is the inverse of an argument created by
zip (under the assumption the a and b have equal length)

Diez

Diez B. Roggisch, Apr 20, 2009

3. ### SakethGuest

On Apr 20, 12:10 pm, Esmail <> wrote:
> Hello all,
>
> I wonder if someone could help me with sorting two corresponding lists.
>
> For instance the first list contains some items, and the second list
> contains their value (higher is better)
>
> items = [apple, car, town, phone]
> values = [5, 2, 7, 1]
>
> I would like to sort the 'items' list based on the 'values' list so
> that I end up with the following two list:
>
> items = [town, apple, car, phone]
> values = [7, 5, 2, 1]
>
> So I would like to keep the corresponding value still corresponding
> after the sorting.
>
> Is there an easy/nice/Pythonic way to do this?
>
> Thanks,
> Esmail

Why not use a dictionary instead of two lists? Then you can sort the
dictionary by value -- e.g.

d = dict(zip(items, values))
sorted_items = sorted(d.iteritems(), key=lambda (k,v): (v,k))

This produces a list of pairs, but demonstrates the general idea.

Saketh, Apr 20, 2009
4. ### EsmailGuest

Hi Diez,

Thanks for this, I had seen zip() before but had no idea
really what it does, this will serve as good motivation to
find out more.

I'm amazed at what this language can do (and the helpfulness
of the people on the list here).

Best,
Esmail

Diez B. Roggisch wrote:

> items = zip(*sorted(zip(values, items)))[1]
>
> To better understand this please note that
>
> a = [1, 2]
> b = [3, 4]
>
> zip(*zip(a, b)) == a, b
>
> or, in other words, zip(*argument) is the inverse of an argument created by
> zip (under the assumption the a and b have equal length)
>
> Diez
> --
> http://mail.python.org/mailman/listinfo/python-list
>

Esmail, Apr 20, 2009
5. ### EsmailGuest

Hi Diez,

Thanks for this, I had seen zip() before but had no idea
really what it does, this will serve as good motivation to
find out more.

I'm amazed at what this language can do (and the helpfulness
of the people on the list here).

Best,
Esmail

Diez B. Roggisch wrote:

> items = zip(*sorted(zip(values, items)))[1]
>
> To better understand this please note that
>
> a = [1, 2]
> b = [3, 4]
>
> zip(*zip(a, b)) == a, b
>
> or, in other words, zip(*argument) is the inverse of an argument created by
> zip (under the assumption the a and b have equal length)
>
> Diez
> --
> http://mail.python.org/mailman/listinfo/python-list
>

Esmail, Apr 20, 2009
6. ### EsmailGuest

Saketh wrote:
>
>
> Why not use a dictionary instead of two lists? Then you can sort the
> dictionary by value -- e.g.

thanks for the suggestion. I am not sure this is quite suitable for my
application (the example I provided was extremely simplified), but this
is a useful technique to know and has been stored away for future use.

Thanks again,
Esmail

Esmail, Apr 20, 2009
7. ### EsmailGuest

Saketh wrote:
>
>
> Why not use a dictionary instead of two lists? Then you can sort the
> dictionary by value -- e.g.

thanks for the suggestion. I am not sure this is quite suitable for my
application (the example I provided was extremely simplified), but this
is a useful technique to know and has been stored away for future use.

Thanks again,
Esmail

Esmail, Apr 20, 2009
8. ### Arnaud DelobelleGuest

Esmail <> writes:

> Hello all,
>
> I wonder if someone could help me with sorting two corresponding lists.
>
> For instance the first list contains some items, and the second list
> contains their value (higher is better)
>
> items = [apple, car, town, phone]
> values = [5, 2, 7, 1]
>
> I would like to sort the 'items' list based on the 'values' list so
> that I end up with the following two list:
>
> items = [town, apple, car, phone]
> values = [7, 5, 2, 1]
>
> So I would like to keep the corresponding value still corresponding
> after the sorting.
>
> Is there an easy/nice/Pythonic way to do this?

One way I have not seen in any reply is to sort the indices first.

>>> values = [5, 2, 7, 1]
>>> items = ['apple', 'car', 'town', 'phone']

Create a list of all indices:

>>> indices = range(len(values))
>>> indices

[0, 1, 2, 3]

Sort the indices according to the value at each index:

>>> indices.sort(key=lambda i: values, reverse=True)
>>> indices

[2, 0, 1, 3]

Now you can get the sorted values and items without further sorting:

>>> [values for i in indices]

[7, 5, 2, 1]
>>> [items for i in indices]

['town', 'apple', 'car', 'phone']

This can be spelt:

>>> map(values.__getitem__, indices)

[7, 5, 2, 1]
>>> map(items.__getitem__, indices)

['town', 'apple', 'car', 'phone']
>>>

HTH

--
Arnaud

Arnaud Delobelle, Apr 20, 2009
9. ### Peter OttenGuest

Esmail wrote:

> I wonder if someone could help me with sorting two corresponding lists.
>
> For instance the first list contains some items, and the second list
> contains their value (higher is better)
>
> items = [apple, car, town, phone]
> values = [5, 2, 7, 1]
>
> I would like to sort the 'items' list based on the 'values' list so
> that I end up with the following two list:
>
> items = [town, apple, car, phone]
> values = [7, 5, 2, 1]

An exotic option:

>>> values = [5, 2, 7, 1]
>>> items = [apple, car, town, phone]
>>> items.sort(key=lambda item, next=iter(values).next: next(),

reverse=True)
>>> values.sort(reverse=True)
>>> items

[town, apple, car, phone]
>>> values

[7, 5, 2, 1]

Peter

Peter Otten, Apr 21, 2009
10. ### Piet van OostrumGuest

>>>>> Saketh <> (S) wrote:

>S> Why not use a dictionary instead of two lists? Then you can sort the
>S> dictionary by value -- e.g.

>S> d = dict(zip(items, values))
>S> sorted_items = sorted(d.iteritems(), key=lambda (k,v): (v,k))

>S> This produces a list of pairs, but demonstrates the general idea.

This will fail if there are duplicates in the items. And if we assume no
duplicates the key doesn't need the k part:

sorted_items = sorted(d.iteritems(), key=lambda (k,v): v)

or

from operator import itemgetter
sorted_items = sorted(d.iteritems(), key=itemgetter(1))

--
Piet van Oostrum <>
URL: http://pietvanoostrum.com [PGP 8DAE142BE17999C4]
Private email:

Piet van Oostrum, Apr 23, 2009
11. ### EsmailGuest

> My solution, I know the 'zip' version is more elegant, this is just for
> fun
>
> >>> items = ['apple', 'car', 'town', 'phone']
> >>> values = [5, 2, 7, 1]
> >>> new_values = sorted(values, reverse = True)
> >>> new_items = [items[x] for x in [i for i in map(values.index,

> new_values)]]
> >>> print(new_values)

> [7, 5, 2, 1]
> >>> print(new_items)

> ['town', 'apple', 'car', 'phone']
> >>>

>

Cool .. always good to know alternative ways of accomplishing

Esmail

Esmail, Apr 23, 2009
12. ### EsmailGuest

> My solution, I know the 'zip' version is more elegant, this is just for
> fun
>
> >>> items = ['apple', 'car', 'town', 'phone']
> >>> values = [5, 2, 7, 1]
> >>> new_values = sorted(values, reverse = True)
> >>> new_items = [items[x] for x in [i for i in map(values.index,

> new_values)]]
> >>> print(new_values)

> [7, 5, 2, 1]
> >>> print(new_items)

> ['town', 'apple', 'car', 'phone']
> >>>

>

Cool .. always good to know alternative ways of accomplishing

Esmail

Esmail, Apr 23, 2009
13. ### Hans DushanthaKumarGuest

Just being pedantic here

[items[x] for x in [i for i in map(values.index, new_values)]]

Is the same as

[items[x] for x in map(values.index, new_values)]

-----Original Message-----
From: python-list-bounces+hans.dushanthakumar=
[mailtoython-list-bounces+hans.dushanthakumar=]
On Behalf Of Esmail
Sent: Friday, 24 April 2009 3:02 AM
To: tiefeng wu
Cc:
Subject: Re: sorting two corresponding lists?

> My solution, I know the 'zip' version is more elegant, this is just

for
> fun
>
> >>> items = ['apple', 'car', 'town', 'phone']
> >>> values = [5, 2, 7, 1]
> >>> new_values = sorted(values, reverse = True)
> >>> new_items = [items[x] for x in [i for i in map(values.index,

> new_values)]]
> >>> print(new_values)

> [7, 5, 2, 1]
> >>> print(new_items)

> ['town', 'apple', 'car', 'phone']
> >>>

>

Cool .. always good to know alternative ways of accomplishing

Esmail
--
http://mail.python.org/mailman/listinfo/python-list

Hans DushanthaKumar, Apr 24, 2009
14. ### Arnaud DelobelleGuest

On Apr 24, 2:32 am, "Hans DushanthaKumar"
<> wrote:
> Just being pedantic here
>
> [items[x] for x in [i for i in map(values.index, new_values)]]
>
> Is the same as
>
> [items[x] for x in map(values.index, new_values)]

It's also the same as

[items[x] for x in [values.index(i) for i in new_values]]

Which reduces to

[items[values.index(i)] for i in new_values]

(Although 'i' is not a good choice of variable as it represents a
value, not an index)

Anyway it doesn't work well if the 'values' list has repeated values,
e.g.

items = ['spam', 'eggs', 'wafer']
values = [3, 7, 3]

--
Arnaud

Arnaud Delobelle, Apr 24, 2009