Sort by price and remove prices

Question:

I have a shopping list:

items = [
    ['Aspirin', 'Walgreens', 6.00],
    ['book lamp', 'Amazon', 2.87],
    ['popsicles', 'Walmart', 5.64],
    ['hair brush', 'Amazon', 6.58],
    ['Listerine', 'Walmart', 3.95],
    ['gift bag', 'Target', 1.50]
]

I want to sort the items from cheapest to highest price, and remove the prices. (I don’t need them anymore then, I’ll just buy from top down until I run out of money). Goal is:

items = [
    ['gift bag', 'Target'],
    ['book lamp', 'Amazon'],
    ['Listerine', 'Walmart'],
    ['popsicles', 'Walmart'],
    ['Aspirin', 'Walgreens'],
    ['hair brush', 'Amazon']
]

A way that works but looks clumsy (demo/template):

import operator
items = sorted(items, key=operator.itemgetter(2))
for i in range(len(items)):
    items[i] = items[i][:2]

Is there a shorter way?

Asked By: Kelly Bundy

||

Answers:

Use the beauty of list comprehension in python.

items = sorted(items, key=lambda x: x[2])
items = [x[:2] for x in items]
Answered By: Kaustubh Dwivedi

What if you use the in built sorted method:

items = [
    ['Aspirin', 'Walgreens', 6.00],
    ['book lamp', 'Amazon', 2.87],
    ['popsicles', 'Walmart', 5.64],
    ['hair brush', 'Amazon', 6.58],
    ['Listerine', 'Walmart', 3.95],
    ['gift bag', 'Target', 1.50]
]
# this sorts by the third element from your each list
new_list = sorted(items, key=lambda x: x[2]) 
    
for i in new_list:
    del i[2]

print(new_list)

Output:

enter image description here

Answered By: Kulasangar

Here is another approach:

items = list(map(lambda x: x[:2], sorted(items, key=lambda x: x[2])))
print(items)

You can also try operator

import operator
items = list(map(operator.itemgetter(0, 1), sorted(items, key=operator.itemgetter(2))))

[['gift bag', 'Target'], ['book lamp', 'Amazon'], ['Listerine', 'Walmart'], ['popsicles', 'Walmart'], ['Aspirin', 'Walgreens'], ['hair brush', 'Amazon']]
Answered By: Jamiu S.

zipzipzip

from operator import itemgetter
from itertools import islice

print(
    list(zip(*islice(zip(*sorted(items, key=itemgetter(-1))),2)))
)
# [('gift bag', 'Target'), ('book lamp', 'Amazon'), ('Listerine', 'Walmart'), ('popsicles', 'Walmart'), ('Aspirin', 'Walgreens'), ('hair brush', 'Amazon')]
Answered By: Stef

Someone suggested I could use more ‘for’ and fewer builtins:

_,items = zip(*sorted((z, x) for *x,z in items))
Answered By: Stef

The inevitable numpy version. Select the first two columns by infering a reordering wrt to the values of the last columns.

import numpy as np

a = np.array(items)

a = a[:,:2][a[:,-1].argsort()]
Answered By: cards

I don’t know how I really feel about using key for side-effects, but:

items.sort(key=list.pop)
print(items)

Result:

[['gift bag', 'Target'], ['book lamp', 'Amazon'], ['Listerine', 'Walmart'], ['popsicles', 'Walmart'], ['Aspirin', 'Walgreens'], ['hair brush', 'Amazon']]
Answered By: slothrop
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.