I have a dictionary where each key is a tuple of values, I want to use the sorted() method to sort the dictionary on the very first element of my tuple. My code looks like this:
def mapData(header_list, dict_obj):
master_dict = {}
client_section_list = []
for element in header_list:
for row in dict_obj:
if (row['PEOPLE_ID'], row['DON_DATE']) == element:
client_section_list.append(row)
element = list(element)
element_list = [client_section_list[0]['DEDUCT_AMT'],
client_section_list[0]['ND_AMT'],
client_section_list[0]['DEDUCT_YTD'],
client_section_list[0]['NONDEDUCT_YTD']
]
try:
element_list.append((float(client_section_list[0]['DEDUCT_YTD']) +
float(client_section_list[0]['NONDEDUCT_YTD'])
))
except ValueError:
pass
element.extend(element_list)
element = tuple(element)
master_dict[element] = client_section_list
client_section_list = []
return sorted(master_dict, key=lambda key: key[master_dict[(1)]]
The last line is where I'm trying to find a way to sort it. My tuple looks like this:
(312178078,6/22/15,25,0,25,0,25.0)
Not entirely sure what you are trying to do, particularly what that function is supposed to return. I assume that you want to return the dictionary sorted by the first element in the key-tuples.
For this, there are two things to note:
Tuples are by default sorted by their first element (and if those are the same, then by the second, and so on), so no special key function is required
Regular dictionaries are unordered, i.e. they can not be permanently sorted in any order; you can only sort their items as a list, or use that list to create an OrderedDict instead
Some minimal example:
>>> d = {(2,4): 1, (1,3): 2, (1,2): 3, (3,1): 4}
>>> sorted(d)
[(1, 2), (1, 3), (2, 4), (3, 1)]
>>> sorted(d.items())
[((1, 2), 3), ((1, 3), 2), ((2, 4), 1), ((3, 1), 4)]
>>> collections.OrderedDict(sorted(d.items()))
OrderedDict([((1, 2), 3), ((1, 3), 2), ((2, 4), 1), ((3, 1), 4)])
In your case, you probably want this:
return collections.OrderedDict(sorted(master_dict.items()))
As #tobias_k has mentioned, sorted sorts tuples by its elements with decreasing priority, e.g. if you take a tuple (a, b, c) the highest sorting priority goes to a, then goes b etc (by default sorted uses object's comparison methods and this is how tuple comparison works). So sorted(master_dict) is all you need if you want a list of sorted keys, yet I believe you really want to leave the values
sorted(master_dict.items(), key=lambda key: key[0])
dict.items returns tuples of form (key, value) so here you need to specify the sorting key.
In the following code, I created a list of lists, like an array. I began getting a "list assignment out of range" error. As a workaround for this error, I added 2 extra instances of diceSumTable, is you can see in the code. It will print now, but it is preceded by "2, 3". In my studying, I can't recall any reason why this would be happening if every instance of diceSumTable is already defined.
EDIT: Here was the original code, without applying the workaround.
def dice():
diceSumTable = [2,3,4,5,6,7,8,9,10,11,12]
diceSumTable[2] = [(1,1)]
diceSumTable[3] = [(1,2),(2,1)]
diceSumTable[4] = [(1,3),(2,2),(3,1)]
diceSumTable[5] = [(1,4),(2,3),(3,2),(4,1)]
diceSumTable[6] = [(1,5),(2,4),(3,3),(4,2),(5,1)]
diceSumTable[7] = [(1,6),(2,5),(3,4),(4,3),(5,2),(6,1)]
diceSumTable[8] = [(2,6),(3,5),(4,4),(5,3),(6,2)]
diceSumTable[9] = [(3,6),(4,5),(5,4),(6,3)]
diceSumTable[10] = [(4,6),(5,5),(6,4)]
diceSumTable[11] = [(5,6),(6,5)]
diceSumTable[12] = [(6,6)]
#for illustrative purposes
for i in diceSumTable:
print i
dice()
As said, you start indexing the diceSumTable from index #2 onward, leaving entries 0 and 1 untouched. The error you got was because you were indexing past the end of the array.
For your problem a "dict" might be a better solution:
diceSumTable = {}
diceSumTable[ 2 ] = [(1,1)]
diceSumTable[ 3 ] = [(1,2), (2,1)]
Try this:
def dice():
diceSumTable = [] # define diceSumTable as a list
diceSumTable.append((1,1)) # append the tuple to diceSumTable
diceSumTable.append(((1,2),(2,1))) # append a tuple of tuples to diceSumTable
diceSumTable.append(((1,3),(2,2),(3,1)))
diceSumTable.append(((1,4),(2,3),(3,2),(4,1)))
diceSumTable.append(((1,5),(2,4),(3,3),(4,2),(5,1)))
diceSumTable.append(((1,6),(2,5),(3,4),(4,3),(5,2),(6,1)))
diceSumTable.append(((2,6),(3,5),(4,4),(5,3),(6,2)))
diceSumTable.append(((3,6),(4,5),(5,4),(6,3)))
diceSumTable.append(((4,6),(5,5),(6,4)))
diceSumTable.append(((5,6),(6,5)))
diceSumTable.append(((6,6)))
#for illustrative purposes
for i in diceSumTable:
print i
dice()
You got 2, 3 because that's what you entered into the list in the first to places, the other numbers you put in got replaced with statements like diceSumTable[x] =.
You are entering data from 2 index (means third element in array).
diceSumTable = [2,3,4,5,6,7,8,9,10,11,12,13,14]
when you do
# Replacing third element
diceSumTable[2] = [(1,1)]
diceSumTable will be like
diceSumTable = [2,3,[(1,1)],5,6,7,8,9,10,11,12,13,14]
Slly it will replace all values.
You are confusing the value of an entry in a list with the index of a list.
diceSumTable[3] corresponds to the fourth entry in diceSumTable (since they are numbered from 0).
Your first line creates a list diceSumTable with 13 entries, numbered 0...12.
Your next set of lines fills in the 3d through 13th entries (and throws away what was there before!).
To do what you want, you have a few choices.
1/ You can do what you're doing, but ignore the first two entries. This is not very pythonic...
2/ You can create a length 11 list, holding the actual entries. In this case, the most efficient way to do it is
diceSumTable = [] ### empty list
diceSumTable.append([(1,1)])
diceSumTable.append([(1,2),(2,1)])
#### etc.
3/ You can use a dict. This is probably closest to what you want, although it's slightly inefficient in space and time, since you just want consecutive integer keys (but premature optimisation is the root of all evil):
diceSumTable = {} ### empty dict
diceSumTable[2] = [(1,1)]
diceSumTable[3] = [(1,2),(2,1)]
#### etc.
(Markdown question: is there any way to intersperse code within a bulleted or enumerated list?)
When you set diceSumTable[2] you are replacing the third value in the list (lists are zero indexed - first value is name[0]) not the value that currently holds 2.
So after the first call you have diceSumTable equal to [2,3,[(1,1)],5,6,...].
I think what you could do is, as mentioned elsewhere, use diceSumTable = [] then diceSumTable.append((1,1)) for each dice combination.
You could also use a dictionary.
diceSumTable = {}
diceSumTable[2] = [(1,1)]
diceSumTable[3] = [(1,2),(2,1)]
#etc
You could then access by value rather than position.
>>>diceSumValue[3]
[(1,2),(2,1)]
>>>
You should index the list by it's indices, not the values:
In [123]: lst = [3, 4, 5]
In [124]: lst[0] == 3 #item "3" is at index 0
Out[124]: True
In [125]: lst[3] #out of range
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-125-48d1ca706e8c> in <module>()
----> 1 lst[3] #out of range
IndexError: list index out of range
In [126]: lst[1] = 10 #if I want to change "4" in the list to "10"
In [127]: lst
Out[127]: [3, 10, 5]
I am not shure of what result do you except from this code, what i understood is that you want to code to print :
[(1, 1)]
[(1, 2), (2, 1)]
[(1, 3), (2, 2), (3, 1)]
[(1, 4), (2, 3), (3, 2), (4, 1)]
[(1, 5), (2, 4), (3, 3), (4, 2), (5, 1)]
[(1, 6), (2, 5), (3, 4), (4, 3), (5, 2), (6, 1)]
[(2, 6), (3, 5), (4, 4), (5, 3), (6, 2)]
[(3, 6), (4, 5), (5, 4), (6, 3)]
[(4, 6), (5, 5), (6, 4)]
[(5, 6), (6, 5)]
[(6, 6)]
In this case, i think the error you are making is believing that the following line :
diceSumTable = [2,3,4,5,6,7,8,9,10,11,12,13,14]
Give you a list where index start from 2 and finish at 14, which is wrong because in Python every list index start at 0, and there is no way you can change that. The line you give me, actually create a list where the first index is 0 and the last index is 12 (size of the list - 1). And you list is such that diceSumTable[0] is 2 diceSumTable[1] is 3, etc.
This lead you to two options, either accept that list start at index 0, and if you want to keep using the mapping you want (i guess there is a reason for that, you surely want to associate 2 with (1,1), 3 with (1,2), (2,1)) just use diceSumTable[theNumberOfYourMapping -2]. Or as say haavee, you can use dict for that. But in this case, when you will iterate over your dict, you won't have you value is the write order. If there is no gap between you're wanted index i will go with the map.
I think it will be great if you could explain use a bit more what you want to do, why do you want 2 and not 0 to be associated to [(1,1)]. Do you want to do something else with this lis t than printing it. To sum up here is the code, i would have written, if i understood what you wanted to do :
def dice():
diceSumTable = [[(1,1)],
[(1,2),(2,1)],
[(1,3),(2,2),(3,1)],
[(1,4),(2,3),(3,2),(4,1)],
[(1,5),(2,4),(3,3),(4,2),(5,1)],
[(1,6),(2,5),(3,4),(4,3),(5,2),(6,1)],
[(2,6),(3,5),(4,4),(5,3),(6,2)],
[(3,6),(4,5),(5,4),(6,3)],
[(4,6),(5,5),(6,4)],
[(5,6),(6,5)],
[(6,6)]]
#this is like for value in diceSumTable but i will iterate to 0,1..10 in more
for (i,value) in enumerate(diceSumTable):
print str(i+2) + " is associated to " + str(value)
dice()
Moreover if you want to know more about Python list, i could read :
http://effbot.org/zone/python-list.htm
And for Python dictionary :
http://www.pythonforbeginners.com/dictionary/dictionary-manipulation-in-pythonc