Python: Tuples/dictionaries as keys, select, sort Python: Tuples/dictionaries as keys, select, sort python python

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