Velocity Reviews > sorting two corresponding lists?

# sorting two corresponding lists?

Esmail
Guest
Posts: n/a

 04-20-2009
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

Diez B. Roggisch
Guest
Posts: n/a

 04-20-2009
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

Saketh
Guest
Posts: n/a

 04-20-2009
On Apr 20, 12:10*pm, Esmail <(E-Mail Removed)> 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.

Esmail
Guest
Posts: n/a

 04-20-2009
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
Guest
Posts: n/a

 04-20-2009
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
Guest
Posts: n/a

 04-20-2009
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
Guest
Posts: n/a

 04-20-2009
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

Arnaud Delobelle
Guest
Posts: n/a

 04-20-2009
Esmail <(E-Mail Removed)> 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[i], reverse=True)
>>> indices

[2, 0, 1, 3]

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

>>> [values[i] for i in indices]

[7, 5, 2, 1]
>>> [items[i] 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

Peter Otten
Guest
Posts: n/a

 04-21-2009
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

Piet van Oostrum
Guest
Posts: n/a

 04-23-2009
>>>>> Saketh <(E-Mail Removed)> (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 <(E-Mail Removed)>
URL: http://pietvanoostrum.com [PGP 8DAE142BE17999C4]
Private email: http://www.velocityreviews.com/forums/(E-Mail Removed)