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?
Answers:
Use the beauty of list comprehension in python.
items = sorted(items, key=lambda x: x[2])
items = [x[:2] for x in items]
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:
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']]
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')]
Someone suggested I could use more ‘for’ and fewer builtins:
_,items = zip(*sorted((z, x) for *x,z in items))
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()]
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']]
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?
Use the beauty of list comprehension in python.
items = sorted(items, key=lambda x: x[2])
items = [x[:2] for x in items]
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:
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']]
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')]
Someone suggested I could use more ‘for’ and fewer builtins:
_,items = zip(*sorted((z, x) for *x,z in items))
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()]
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']]