I have a list similar to the following:
my_list =
[(1, 'item_19'),
(2, 'item_20'),
(3, 'item_21'),
(4, 'item_22'),
(5, 'item_23'),
(6, 'item_24'),
(7, 'item_25'),
(8, 'item_26'),
(9, 'item_27'),
(10, 'item_28'),
(11, 'item_29'),
(12, 'item_30'),
(13, 'item_31'),
(14, 'item_32'),
(15, 'item_33'),
(16, 'item_34'),
(17, 'item_35')]
I would like to make a dictionary of each element of the list, i.e. 1:'item_19',2:'item_20'
I currently do this:
list_1 = [l[0] for l in my_list]
list_2 = [l[1] for l in my_list]
and then zip the two lists
my_dict = dict(zip(list_1,list_2))
However there are more than a million element in my_list, so is this the best way to do this, or is there a quicker/more optimal way to do it(Memory wise).
To put this in context, I want a lookup table to check if elements in my_dict already exist in a different dictionary my_dict_old
The builtin dict function takes a list of tuples, which is exactly what you are providing:
>>> list_foo = [(1, 'item_1'), (2, 'item_2')]
>>> dict(list_foo)
{1: 'item_1', 2: 'item_2'}
If all you need to do is check for an item's existence, consider using set, as i in my_set is much faster than i in my_dict.values(), see the Python documentation on performance for more info. On my machine, for example, a lookup in a haystack of 10k entries is .443s with dict.values(), vs <.000s for set. If you need to associate values with the entries, then use a dictionary, otherwise use a set. For a more in-depth examination of lists vs. dictionaries (and also sets for the most part), refer to this answer.
dict accepts list of tuples, so you can just use your original list:
my_dict = dict(my_list)
And you are actually doing the same thing while calling zip
Also, if all keys are numbers and are not huge you can put all of them into array. Index would be the key. Though this solution depends on the actual task and might not be useful in some cases
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.
This question already has answers here:
How to get the cartesian product of multiple lists
(17 answers)
Closed 8 months ago.
I have a dictionary:
mydict = {'item1':[1,2,3],'item2':[10,20,30]}
I want to create the cartesian product of the two so that I get a tuple of each possible pair.
output: [(1,10),(1,20),(1,30),
(2,10),(2,20),(2,30),
(3,10),(3,20),(3,30)]
It seems like there would be a simple way to do this so that it extends if I have three items. Kind of like a dynamic number of loops. Feels like I am missing an obvious way to do this...
The itertools.product() function will do this:
>>> import itertools
>>> mydict = {'item1':[1,2,3],'item2':[10,20,30]}
>>> list(itertools.product(*mydict.values()))
[(10, 1), (10, 2), (10, 3), (20, 1), (20, 2), (20, 3), (30, 1), (30, 2), (30, 3)]
If you need to control the order of the resulting tuples, you can do
itertools.product(mydict['item1'], mydict['item2'])
You can also brute force it using two loops
mydict = {'item1':[1,2,3],'item2':[10,20,30]}
x = []
for i in mydict['item1']:
for j in mydict['item2']:
x.append((i,j))
All this code does is go through all of the item in mydict['item1'], then through each item in mydict['item2'], then appends a pair of each to a new list.
It will give you this result:
[(1, 10), (1, 20), (1, 30), (2, 10), (2, 20), (2, 30), (3, 10), (3, 20), (3, 30)]
You can use List Comprehensions:
[(i, j) for i in mydict['item1'] for j in mydict['item2']]
you could do two for loops.
- the first one would keep track of the index position of the first item list.
-The second loop would go through each item in the second.
- After it runs through all the items, the first for loop would increment to the next item in its list and the second loop will run through the second list again, etc.
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