Python: Tuples/dictionaries as keys, select, sort
Personally, one of the things I love about python is the tuple-dict combination. What you have here is effectively a 2d array (where x = fruit name and y = color), and I am generally a supporter of the dict of tuples for implementing 2d arrays, at least when something like numpy
or a database isn't more appropriate. So in short, I think you've got a good approach.
Note that you can't use dicts as keys in a dict without doing some extra work, so that's not a very good solution.
That said, you should also consider namedtuple(). That way you could do this:
>>> from collections import namedtuple>>> Fruit = namedtuple("Fruit", ["name", "color"])>>> f = Fruit(name="banana", color="red")>>> print fFruit(name='banana', color='red')>>> f.name'banana'>>> f.color'red'
Now you can use your fruitcount dict:
>>> fruitcount = {Fruit("banana", "red"):5}>>> fruitcount[f]5
Other tricks:
>>> fruits = fruitcount.keys()>>> fruits.sort()>>> print fruits[Fruit(name='apple', color='green'), Fruit(name='apple', color='red'), Fruit(name='banana', color='blue'), Fruit(name='strawberry', color='blue')]>>> fruits.sort(key=lambda x:x.color)>>> print fruits[Fruit(name='banana', color='blue'), Fruit(name='strawberry', color='blue'), Fruit(name='apple', color='green'), Fruit(name='apple', color='red')]
Echoing chmullig, to get a list of all colors of one fruit, you would have to filter the keys, i.e.
bananas = [fruit for fruit in fruits if fruit.name=='banana']
Database, dict of dicts, dictionary of list of dictionaries, named tuple (it's a subclass), sqlite, redundancy... I didn't believe my eyes. What else ?
"It might well be that dictionaries with tuples as keys are not the proper way to handle this situation."
"my gut feeling is that a database is overkill for the OP's needs; "
Yeah! I thought
So, in my opinion, a list of tuples is plenty enough :
from operator import itemgetterli = [ ('banana', 'blue' , 24) , ('apple', 'green' , 12) , ('strawberry', 'blue' , 16 ) , ('banana', 'yellow' , 13) , ('apple', 'gold' , 3 ) , ('pear', 'yellow' , 10) , ('strawberry', 'orange' , 27) , ('apple', 'blue' , 21) , ('apple', 'silver' , 0 ) , ('strawberry', 'green' , 4 ) , ('banana', 'brown' , 14) , ('strawberry', 'yellow' , 31) , ('apple', 'pink' , 9 ) , ('strawberry', 'gold' , 0 ) , ('pear', 'gold' , 66) , ('apple', 'yellow' , 9 ) , ('pear', 'brown' , 5 ) , ('strawberry', 'pink' , 8 ) , ('apple', 'purple' , 7 ) , ('pear', 'blue' , 51) , ('chesnut', 'yellow', 0 ) ]print set( u[1] for u in li ),': all potential colors'print set( c for f,c,n in li if n!=0),': all effective colors'print [ c for f,c,n in li if f=='banana' ],': all potential colors of bananas'print [ c for f,c,n in li if f=='banana' and n!=0],': all effective colors of bananas'printprint set( u[0] for u in li ),': all potential fruits'print set( f for f,c,n in li if n!=0),': all effective fruits'print [ f for f,c,n in li if c=='yellow' ],': all potential fruits being yellow'print [ f for f,c,n in li if c=='yellow' and n!=0],': all effective fruits being yellow'printprint len(set( u[1] for u in li )),': number of all potential colors'print len(set(c for f,c,n in li if n!=0)),': number of all effective colors'print len( [c for f,c,n in li if f=='strawberry']),': number of potential colors of strawberry'print len( [c for f,c,n in li if f=='strawberry' and n!=0]),': number of effective colors of strawberry'print# sorting li by name of fruitprint sorted(li),' sorted li by name of fruit'print# sorting li by number print sorted(li, key = itemgetter(2)),' sorted li by number'print# sorting li first by name of color and secondly by name of fruitprint sorted(li, key = itemgetter(1,0)),' sorted li first by name of color and secondly by name of fruit'print
result
set(['blue', 'brown', 'gold', 'purple', 'yellow', 'pink', 'green', 'orange', 'silver']) : all potential colorsset(['blue', 'brown', 'gold', 'purple', 'yellow', 'pink', 'green', 'orange']) : all effective colors['blue', 'yellow', 'brown'] : all potential colors of bananas['blue', 'yellow', 'brown'] : all effective colors of bananasset(['strawberry', 'chesnut', 'pear', 'banana', 'apple']) : all potential fruitsset(['strawberry', 'pear', 'banana', 'apple']) : all effective fruits['banana', 'pear', 'strawberry', 'apple', 'chesnut'] : all potential fruits being yellow['banana', 'pear', 'strawberry', 'apple'] : all effective fruits being yellow9 : number of all potential colors8 : number of all effective colors6 : number of potential colors of strawberry5 : number of effective colors of strawberry[('apple', 'blue', 21), ('apple', 'gold', 3), ('apple', 'green', 12), ('apple', 'pink', 9), ('apple', 'purple', 7), ('apple', 'silver', 0), ('apple', 'yellow', 9), ('banana', 'blue', 24), ('banana', 'brown', 14), ('banana', 'yellow', 13), ('chesnut', 'yellow', 0), ('pear', 'blue', 51), ('pear', 'brown', 5), ('pear', 'gold', 66), ('pear', 'yellow', 10), ('strawberry', 'blue', 16), ('strawberry', 'gold', 0), ('strawberry', 'green', 4), ('strawberry', 'orange', 27), ('strawberry', 'pink', 8), ('strawberry', 'yellow', 31)] sorted li by name of fruit[('apple', 'silver', 0), ('strawberry', 'gold', 0), ('chesnut', 'yellow', 0), ('apple', 'gold', 3), ('strawberry', 'green', 4), ('pear', 'brown', 5), ('apple', 'purple', 7), ('strawberry', 'pink', 8), ('apple', 'pink', 9), ('apple', 'yellow', 9), ('pear', 'yellow', 10), ('apple', 'green', 12), ('banana', 'yellow', 13), ('banana', 'brown', 14), ('strawberry', 'blue', 16), ('apple', 'blue', 21), ('banana', 'blue', 24), ('strawberry', 'orange', 27), ('strawberry', 'yellow', 31), ('pear', 'blue', 51), ('pear', 'gold', 66)] sorted li by number[('apple', 'blue', 21), ('banana', 'blue', 24), ('pear', 'blue', 51), ('strawberry', 'blue', 16), ('banana', 'brown', 14), ('pear', 'brown', 5), ('apple', 'gold', 3), ('pear', 'gold', 66), ('strawberry', 'gold', 0), ('apple', 'green', 12), ('strawberry', 'green', 4), ('strawberry', 'orange', 27), ('apple', 'pink', 9), ('strawberry', 'pink', 8), ('apple', 'purple', 7), ('apple', 'silver', 0), ('apple', 'yellow', 9), ('banana', 'yellow', 13), ('chesnut', 'yellow', 0), ('pear', 'yellow', 10), ('strawberry', 'yellow', 31)] sorted li first by name of color and secondly by name of fruit
Your best option will be to create a simple data structure to model what you have. Then you can store these objects in a simple list and sort/retrieve them any way you wish.
For this case, I'd use the following class:
class Fruit: def __init__(self, name, color, quantity): self.name = name self.color = color self.quantity = quantity def __str__(self): return "Name: %s, Color: %s, Quantity: %s" % \ (self.name, self.color, self.quantity)
Then you can simply construct "Fruit" instances and add them to a list, as shown in the following manner:
fruit1 = Fruit("apple", "red", 12)fruit2 = Fruit("pear", "green", 22)fruit3 = Fruit("banana", "yellow", 32)fruits = [fruit3, fruit2, fruit1]
The simple list fruits
will be much easier, less confusing, and better-maintained.
Some examples of use:
All outputs below is the result after running the given code snippet followed by:
for fruit in fruits: print fruit
Unsorted list:
Displays:
Name: banana, Color: yellow, Quantity: 32Name: pear, Color: green, Quantity: 22Name: apple, Color: red, Quantity: 12
Sorted alphabetically by name:
fruits.sort(key=lambda x: x.name.lower())
Displays:
Name: apple, Color: red, Quantity: 12Name: banana, Color: yellow, Quantity: 32Name: pear, Color: green, Quantity: 22
Sorted by quantity:
fruits.sort(key=lambda x: x.quantity)
Displays:
Name: apple, Color: red, Quantity: 12Name: pear, Color: green, Quantity: 22Name: banana, Color: yellow, Quantity: 32
Where color == red:
red_fruit = filter(lambda f: f.color == "red", fruits)
Displays:
Name: apple, Color: red, Quantity: 12