How can I sort a zipped object?

Hi!
I had a different question:
Let’s say I want to add indexes to the cities_list with a zip()-function:

cities = ['London', 'Paris', 'Rome', 'Los Angeles', 'New York']
ind = list(range(5))
zip_cities = zip(cities, ind)

print(list(zip_cities))

This will output the cities unsorted. If I wanted to sort them alphabetically now, but keep the index numbers the same I would add

sorted_cities = zip_cities.sort()

by intuition. However, this would return:

    sorted_cities = zip_cities.sort()
AttributeError: 'zip' object has no attribute 'sort'

How would I sort such a list alphabetically?
(In other words: Iwant to have [('London', 0), ('Los Angeles', 3), ('New York', 4), ('Paris', 1), ('Rome', 2)] as output.)

>>> help([].sort)
Help on built-in function sort:

sort(*, key=None, reverse=False) method of builtins.list instance
    Sort the list in ascending order and return None.
    
    The sort is in-place (i.e. the list itself is modified) and stable (i.e. the
    order of two equal elements is maintained).
    
    If a key function is given, apply it once to each list item and sort them,
    ascending or descending, according to their function values.
    
    The reverse flag can be set to sort in descending order.

I don’t really understand this help text, but the next lesson is about sorted() and it worked with:

cities = ['London', 'Paris', 'Rome', 'Los Angeles', 'New York']
ind = list(range(5))
zip_cities = zip(cities, ind)

sorted_cities = sorted(zip_cities)
print(list(sorted_cities))

Oops, I got a bit selective about which parts of your post I read.

zip doesn’t return a list, and what it does return doesn’t implement a method named sort (read your error message)

sorted on the other hand, accepts any iterable, and the value that zip creates is indeed iterable.

if you read the part about key in list’s sort method’s doc text, that says something about how you can sort BY something, so you could sort by length or by second value and so on, you provide the function that extracts the relevant information

if you compare tuples, then what tuple will do is compare the first values, and if they’re equal compare the second and so on, which means that if you put the value you care to sort by first, then tuples are already ordered that way

sorted offers the same behaviour, it too accepts a key to sort by

Just tried it out with len. Now, I get it! Thx! :slight_smile:

toppings =[‘pepperoni’,‘pineaaple’,‘cheese’,‘sausage’,‘olives’,‘anchovies’,‘mushrooms’]

prices = [2,6,1,3,2,7,2]

pizzas = list(zip(prices,toppings))

pizzas.sort()

print(pizzas)

In the above query the sorting will happen according to prices in pizzas

However if we want to sort as per toppings , is there any way?

Recall the order in which the zip object is derived… prices, toppings. What happens when we reverse that order then sort?


Eg.

zip(prices, toppings)

vs.

zip(toppings, prices)

The default sort will use the first element in each tuple as we will have witnessed.

There are ways that we can ignore the order, as such, and simply note which element each object occupies. If we know the topping is at index 0 and the price at index 1, we can use a key parameter to specify which index other than zero to sort by.

pizzas = sorted(list(zip(toppings, prices)), key=lambda x: x[1])
print (pizzas)
# [('cheese', 1), ('pepperoni', 2), ('olives', 2), ('mushrooms', 2), ('sausage', 3), ('pineaaple', 6), ('anchovies', 7)]

The lambda syntax may not be familiar, so some extra study will be in the cards. Think of it as an anonymous function that acts upon each value in the iterable.

Python has a module called, operator that abstracts the above lambda with itemgetter.

from operator import itemgetter
pizzas = sorted(list(zip(toppings, prices)), key=itemgetter(1))
print (pizzas)
# [('cheese', 1), ('pepperoni', 2), ('olives', 2), ('mushrooms', 2), ('sausage', 3), ('pineaaple', 6), ('anchovies', 7)]

https://docs.python.org/3/howto/sorting.html