-1

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?

Kelly Bundy
  • 23,480
  • 7
  • 29
  • 65
  • @closer Bah, I wish you had more faith in me :-). There's a neat and educational solution that I'd like people to find and see. It's not on SO, I checked the database. Even Google finds only one case. – Kelly Bundy Feb 10 '23 at 11:59
  • Can you clarify the "buy until I run out of money" part, please? The code you've provided makes no comparison to a total price. – gvee Feb 10 '23 at 12:02
  • @gvee That's just the reason for why I don't need the prices anymore. Not part of the task. – Kelly Bundy Feb 10 '23 at 12:03
  • 1
    By creating a new object a naively `map(operator.itemgetter(0, 1), sorted(...))` – cards Feb 10 '23 at 12:10
  • there is https://codegolf.stackexchange.com/ – Juraj Feb 10 '23 at 18:53
  • @Juraj I know. But this isn't. – Kelly Bundy Feb 10 '23 at 19:03
  • If anyone wonders about that one previous case [Google](https://www.google.com/search?q=python+%22key%3Dlist.pop%22) found: it was in [2007-April.txt - Python mailing list](https://mail.python.org/pipermail/python-list/2007-April.txt). – Kelly Bundy Feb 10 '23 at 19:15
  • Oops, actually I overlooked one there, and it *is* [on Codegolf](https://codegolf.stackexchange.com/a/222973/110278), haha @Juraj – Kelly Bundy Feb 10 '23 at 19:18

7 Answers7

5

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']]
Sunderam Dubey
  • 1
  • 11
  • 20
  • 40
slothrop
  • 3,218
  • 1
  • 18
  • 11
2

Use the beauty of list comprehension in python.

items = sorted(items, key=lambda x: x[2])
items = [x[:2] for x in items]
Kaustubh Dwivedi
  • 418
  • 4
  • 16
2

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

Kulasangar
  • 9,046
  • 5
  • 51
  • 82
2

Someone suggested I could use more 'for' and fewer builtins:

_,items = zip(*sorted((z, x) for *x,z in items))
Stef
  • 13,242
  • 2
  • 17
  • 28
  • Nah, no `for` intended. I was just joking regarding your first code here and [this](https://stackoverflow.com/questions/75385452/how-would-i-get-a-list-of-pairs-where-every-element-from-list1-is-paired-with-so/75395480#comment133025713_75385676). – Kelly Bundy Feb 10 '23 at 15:42
  • This is nice, but the intended solution is half as long. – Kelly Bundy Feb 10 '23 at 15:44
1

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']]
Jamiu S.
  • 5,257
  • 5
  • 12
  • 34
1

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')]
Stef
  • 13,242
  • 2
  • 17
  • 28
1

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()]
cards
  • 3,936
  • 1
  • 7
  • 25