How to force dictionary elements to be written in order? - python

I am trying to write from Python into an Excel workbook using XlsxWriter.
I have a dictionary called Pg whose keys are tuples.
for key,value in Pg.iteritems():
for t in range(1,4):
if key==(0,t):
worksheet.write(row,col,value.x)
row += 1
I want to write values of key (0,t) in a column, but the values don't appear in normal order. For example, if my dictionary looks like this:
Pg={(0,1):1,(0,2):2,(0,3):3}
I get in Excel:
1
3
2
Why is this happening when I have strictly determined in the second for loop how I want my values to be written?

I think you realize that when you iterate over a dictionary, you are not guaranteed any specific ordering. The problem you are having is that the way you are trying to force an ordering is flawed.
for key,value in Pg.iteritems():
for t in range(1,4):
if key==(0,t):
# ...
What this does is iterate over each key, value pair first. Then inside this you output if the key matches a certain condition. If you switched the ordering of the for loops, you would get what you wanted, but this method is not efficient at all.
More simply, you can iterate over the sorted dictionary like this:
for key, value in sorted(Pg.iteritems()):
worksheet.write(row, col, value.x)
row += 1

Related

Python read tuples from dictionary

I'm stucked with reading value from my dictionary. My dictionary is like a = {(1,2):(1,2,3,4),(4,5,6,7),...} and my task is to loop value, e.g.,(1,2,3,4) and read value[0] and value[1], in this case, is 1 and 2.
But when I'm not sure if there is a tuple or multiple tuples in value, how can I loop the value and read the first and second value of tuple? I mean, if I use for loop directly towards a, then the result of loop is a value rather than a tuple. How could I deals with this situation? My only thinking is add if statement but I wonder if there is more efficient way. :)
You can loop over the keys in the dictionary and then pull each tuple from the dictionary and loop over those, like so:
for key in dict:
for tuple in dict[key]:
# whatever you want to do with tuple[0] and tuple[1]

How can I get a ranked list from a dictionary?

I am working in Python. The dictionary I have looks like this:
score = {'a':{4:'c', 3:'d'}, 'b':{6:'c', 3:'d'}}
And I need to order it like this:
rank = [{a:3, b:6}, {a:4, b:3}]
Where the sub-dictionary with the greatest combination of exclusive key values is in the first element, the second greatest combination of exclusive key values is in the second element and so forth. The greatest combination logic would be: 1. Grab the biggest combination (total sum) of keys from each dictionary (in this case it would be a->4:'c' and b->6:'d'. Remove those values from the dictionary and grab the next biggest combination of keys (in this case, it would be a->4:'c' and b->3:'d'). This should continue until the original dictionary is empty.
It is exclusive because once the once a value has been used from the original dict, it should be removed, or excluded from being used again in any future combinations.
I have tried all the different approaches I know, but algorithmically I am missing something.
I think I made what you're looking for? It's a weird algorithm, and it's kinda dirty due to the try/except block, but it works.
Edit: added comments and removed unneeded code.
def rank(toSort):
#importing from the string library
from string import lowercase as alph
#temporary list
_ranks=[]
#populate with empty dictonaries
for i in range(len(toSort)):
_ranks.append({})
#the actual sorting algorithm
for i in range(len(toSort)-1):
#iterate all k/v pairs in the supplied dictionary
for k,v in toSort.iteritems():
#iterate all k/v pairs in v element
for a,b in v.iteritems():
#if the alpha index of an element is equal to
#the max alpha index of elements in its containing dictionary...
if alph.index(b)==max(map(alph.index,v.values())):
_ranks[i][k]=a
#if it isn't..
else:
try:
_ranks[i+1][k]=a
except IndexError:
_ranks[-1][k]=a
return _ranks

searching a value in a list and outputting its key

i have a dictionary, in which each key has a list as its value and those lists are of different sizes. I populated keys and values using add and set(to avoid duplicates). If i output my dictionary, the output is:
blizzard set(['00:13:e8:17:9f:25', '00:21:6a:33:81:50', '58:bc:27:13:37:c9', '00:19:d2:33:ad:9d'])
alpha_jian set(['00:13:e8:17:9f:25'])
Here, blizzard and alpha_jian are two keys in my dictionary.
Now, i have another text file which has two columns like
00:21:6a:33:81:50 45
00:13:e8:17:9f:25 59
As you can see, the first column items are one of the entries in each list of my dictionary. For example, 00:21:6a:33:81:50 belongs to the key 'blizzard' and 00:13:e8:17:9f:25 belongs to the key 'alpha_jian'.
The problem i want is, go through first column items in my text file, and if that column entry is found in dictionary, find its corresponding key, find the length of that corresponding list in the dictionary, and add them in new dictionary, say newDict.
For example 00:21:6a:33:81:50 belongs to blizzard. Hence, newDict entry will be:
newDict[blizzard] = 4 // since the blizzard key corresponds to a list of length 4.
This is the code i expected to do this task:
newDict = dict()
# myDict is present with entries like specified above
with open("input.txt") as f:
for line in f:
fields = line.split("\t")
for key, value in myDict.items():
if fields[0] == #Some Expression:
newdict[key] = len(value)
print newDict
Here, my question is what should be #Some Expression in my code above. If values are not lists, this is very easy. But how to search in lists? Thanks in advance.
You are looking for in
if fields[0] in value:
But this isn't a very efficient method, as it involves scanning the dict values over and over
You can make a temporary datastructure to help
helper_dict = {k: v for v, x in myDict.items() for k in x}
So your code becomes
helper_dict = {k: v for v, x in myDict.items() for k in x}
with open("input.txt") as f:
for line in f:
fields = line.split("\t")
key = fields[0]
if key in helper_dict:
newdict[helper_dict[key]] = len(myDict[helper_dict[key]])
Doesn't
if fields[0] in value:
solve your problem ? Or I don't understand your question ?
Looks like
if fields[0] in value:
should do the trick. I.e. check if the field is a member of the set (this also works for lists, but a bit slower at least if the lists are large).
(note that lists and sets are two different things; one is an ordered container that can contain multiple copies of the same value, the other an unordered container that can contain only one copy of each value.)
You may also want to add a break after the newdict assignment, so you don't keep checking all the other dictionary entries.
if fields[0] in value: should do the trick given that from what you say above every value in the dictionary is a set, whether of length 1 or greater.
It would probably be more efficient to build a new dictionary with keys like '00:13:e8:17:9f:25' (assuming these are unique), and associated values being the number of entries in their set before you start though - that way you will avoid recalculating this stuff repeatedly. Obviously, if the list isn't that long then it doesn't make much difference.

Removing one element from an entire dictionary

I've been working on this thing for hours, still cant figure it out :O
The problem I'm having is this. Lets say I have a dictionary with 4-element tuples as elemets and an integer as key. When an element is removed from the whole dictionary (which belongs to every tuple) making two of the tuples (elements) same, the keys of the two tuples don't add up. Instead, a new element is formed, with the key for that element being one of the previous 2 keys.
Let's say I have a dictionary:
dict={('A','B','D','C'): 4, ('C','B','A','D'):5, ('D','A','C','B'):3,('D','A','B','C'):1}
Now I wanna remove one letter from the entire dictionary.
for example, If I wanna remove 'B'. The following new dictionary is formed, but isn't returned, because two of the elements are the same.
{('A','D','C'): 4, ('C','A','D'):5, ('D','A','C'):3,('D','A','C'):1}
Instead of ('D','A','C'):3,('D','A','C'):1 becoming ('D','A','C'):4, this is what ends up happenening:
('D','A','C'):3 along with other tuples
So basically, one of the tuples disappears.
This is the method I'm currently using:
for next in dict:
new_tuple=()
for i in next:
if i!='A':
new_tuple+=(i,)
new_dict[new_tuple]=dict[next]
The above code returns new_dict as the following:
{('A','D','C'): 4, ('C','A','D'):5, ('D','A','C'):3}
So what can I do, to remove one letter from every tuple in the entire dictionary, and if two of the tuples look the same, they merge and the keys add up?
You will have to rebuild your entire dictionary, as each key/value pair is going to be affected. You can use a defaultdict to make the merging easier when you encounter now-overlapping keys:
from collections import defaultdict
new_dict = defaultdict(int)
for key, value in old_dict.items():
new_key = tuple(i for i in key if i != 'A')
new_dict[new_key] += value
Because when first looking up new_key in new_dict it'll be set to 0 by default, all we have to do is add the old value to update new_dict for when we first encounter a key. The next time we encounter the key the values are 'merged' by adding them up.

Python: compare keys of 2 dictionaries and update the value of one

I have 2 dictionaries with the same keys:
d={123:'bla', 456: blabla}
e={123:'bla', 456:''}
Dictionary e has some empty values and if this is the case and the IDs are the same I'd like to replace the empty value with the value from d.
I am looking for something like this:
if d.keys()==e.keys():
e.values==d.values()
print e
However, I couldn't find anything in the Python documentation that compares single keys and updates the values.
Can someone help or point me at something?
Thanks :)
You can do a straight update if you don't mind overwriting differing values with
e.update(d)
or if you want to make sure you only overwrite the ones containing empty values then you will need to iterate over your dictionary to find them, and update selectively
# Python 2.x
for key, value in e.iteritems():
if value == '':
e[key] = d.get(key)
# Python 3.x
for key, value in e.items():
if value == '':
e[key] = d.get(key)
You can also use a dict comprehension:
f = {k:(e[k] or d[k]) for k in e.keys()}
or evaluates to the second item if the first is empty. Of course you have to make sure both use the same keys.

Categories

Resources