How to iterate while for values in a dictionary? - python

I'm a new programmer. I need help with my code. In code, I have a dictionary that its values are a list. I want to do something in 'while' until the dictionary has a value. I used while(len(migration))!= 0, but it's not correct. How can I iterate while for all values in a dictionary?
At the end of while, I want to delete values in the dictionary, but I don't know how can I do this and update my dictionary's values.
migration_p = {2: [3, 4], 3: [3]}
def q_sequence():
global p, sequence_q, r_s, d_s, d, partition, migration_p
while len(migration_p) != 0:
sequence_qi = []
migration_pi = copy.deepcopy(migration_p)
while len(migration_pi) != 0:
tqi_min = math.inf
for p in migration_pi.keys():
# if len(migration_pi[p]) < M - A:
for d in migration_pi[p]:
for r_src in migration_pi.keys():
if r_src not in sequence_qi:
xx = time_qi(d, p)[0]
if xx < tqi_min:
tqi_min = xx
r_s = r_src
d_s = d
sequence_qi.append([(time_qi(d, p)[1], d_s), r_s])
migration_pi = {p: d for p, d in migration_pi.items() if p != r_s}
migration_pi = {p: d for p, d in migration_pi.items() if (p != r_s or d != d_s)}
sequence_q.append(sequence_qi)
# print(sequence_q)
break
return sequence_q
I expect the output to be [[[(1, 3), 2], [(1, 3), 3]]] but the actual output is [[[(1, 3), 2], [(1, 3), 3], [(2, 4), 2]]].

To iterate on values
for value in dictionary.values():
...

do this to retrieve pair of key and value
for key, value in yourDictionary:
print "this is key : "+key
print "this is value : "+value

for key in migration.keys():
print "Key: " + key
print "Value " + migration.pop(key) # This will delete the key from your dict and return a value
migration[key] = new_value # This will create the key again and update it's value

Would it help to know there's a built in way to iterate over all entries in a dictionary?
I can't remember exactly, but it is something to the effect of
for key in nameOfDictionary:
print(nameOfDictionary[key])
Then if after you did all of your iterative stuff, you could make it delete the dictionary by doing something like this.
for key in nameOfDictionary:
print(nameOfDictionary[key])
del nameOfDictionary
Optionally, if you want the dictionary to still exist, you can use nameOfDictionary.clear to simply remove all entries.

Related

Top Three Values in a Dictionary, No Repeated Values

I want to be able to print the top three values in a dictionary created in another function, where there may be repeating values.
For example, if I have a dictionary d = { a:1, b:2, c:3, d:3, e:4 } I would only want a, b, and c returned.
This is what I currently have, but the output would be a, b, c, d. I don't want to remove d from the dictionary, I just don't want it returned when I run this function.
def top3(filename: str):
"""
Takes dict defined in wd_inventory, identifies top 3 words in dict
:param filename:
:return:
"""
d = max_frequency(filename)
x = list(d.values())
x.sort(reverse=True)
y = set(x)
x = x[0:3]
for i in x:
for j in d.keys():
if d[j] == i:
print(str(j) + " : " + str(d[j]))
return
One solution could be the following:
d = { "a":3, "b":4, "c":2, "d":5, "e":1}
print(sorted(d.items(), key=lambda x: x[1])[:3])
OUTPUT
[('e', 1), ('c', 2), ('a', 3)]
Note that will return truly the top 3 entry (by value), not the ones with keys 1, 2 and 3.
EDIT
I don't know what repeating value means exactly, but let's assume that in a dictionary like:
d = {"a":1, "b": 2, "c": 3, "d": 1, "e": 1}
You would like to print just a, b and c (given that d and e repeat the same value as a)
You could use the following approach:
from collections import defaultdict
res = defaultdict(list)
for key, val in sorted(d.items()):
res[val].append(key)
print([y[0] for x, y in list(res.items())])
OUTPUT
['a', 'b', 'c']
You can use heapq.nsmallest() to get the n smallest values in an iterable. This might be especially useful if the dict is very large, because it saves sorting a whole list only to select just three elements of it.
from heapq import nsmallest
from operator import itemgetter
def top3(dct):
return nsmallest(3, dct.items(), key=itemgetter(1))
dct = {'a':1, 'b':2, 'c':3, 'd':3, 'e':4}
for k, v in top3(dct):
print(f"{k}: {v}")
Output
a: 1
b: 2
c: 3
Due credit: I copied parts of j1-lee's code to use as a template.
[edited]
sorry, i have overseen that the smallest number has the highest status.
the code now is sorting the dictionary. this creates a list of tuples.
dic = {'aaa':3, 'xxx':1, 'ccc':8, 'yyy': 4, 'kkk':12}
res = sorted(dic.items(), key=lambda x: x[1])
print(res[:3])
result is:
[('xxx', 1), ('aaa', 3), ('yyy', 4)]

Match list's index based off its value

I am new to Python and working on a problem where I have to match a list of indices to a list of value with 2 conditions:
If there is a repeated index, then the values should be summed
If there is no index in the list, then value should be 0
For example, below are my 2 lists: 'List of Inds' and 'List of Vals'. So at index 0, my value is 5; at index 1, my value is 4; at index 2, my value is 3 (2+1), at index 3, may value 0 (since no value associated with the index) and so on.
Input:
'List of Inds' = [0,1,4,2,2]
'List Vals' = [5,4,3,2,1]
Output = [5,4,3,0,3]
I have been struggling with it for few days and can't find anything online that can point me in the right direction. Thank you.
List_of_Inds = [0,1,4,2,2]
List_Vals = [5,4,3,2,1]
dic ={}
i = 0
for key in List_of_Inds:
if key not in dic:
dic[key] = 0
dic[key] = List_Vals[i]+dic[key]
i = i+1
output = []
for key in range(0, len(dic)+1):
if key in dic:
output.append(dic[key])
else:
output.append(0)
print(dic)
print(output)
output:
{0: 5, 1: 4, 4: 3, 2: 3}
[5, 4, 3, 0, 3]
The following code works as desired. In computer science it is called "Sparse Matrix" where the data is kept only for said indices, but the "virtual size" of the data structure seems large from the outside.
import logging
class SparseVector:
def __init__(self, indices, values):
self.d = {}
for c, indx in enumerate(indices):
logging.info(c)
logging.info(indx)
if indx not in self.d:
self.d[indx] = 0
self.d[indx] += values[c]
def getItem(self, key):
if key in self.d:
return self.d[key]
else:
return 0
p1 = SparseVector([0,1,4,2,2], [5,4,3,2,1])
print p1.getItem(0);
print p1.getItem(1);
print p1.getItem(2);
print p1.getItem(3);
print p1.getItem(4);
print p1.getItem(5);
print p1.getItem(6);
Answer code is
def ans(list1,list2):
dic={}
ans=[]
if not(len(list1)==len(list2)):
return "Not Possible"
for i in range(0,len(list1)):
ind=list1[i]
val=list2[i]
if not(ind in dic.keys()):
dic[ind]=val
else:
dic[ind]+=val
val=len(list1)
for i in range(0,val):
if not(i in dic.keys()):
ans.append(0)
else:
ans.append(dic[i])
return ans
To test:
print(ans([0,1,4,2,2], [5,4,3,2,1]))
output:
[5, 4, 3, 0, 3]
Hope it helps
Comment if you dont understand any step
what you can do is sort the indexes and values in an ascending order, and then sum it up. Here is an example code:
import numpy as np
ind = [0,1,4,2,2]
vals = [5,4,3,2,1]
points = zip(ind,vals)
sorted_points = sorted(points)
new_ind = [point[0] for point in sorted_points]
new_val = [point[1] for point in sorted_points]
output = np.zeros((len(new_ind)))
for i in range(len(new_ind)):
output[new_ind[i]] += new_val[i]
In this code, the index values are sorted to be in ascending order and then the value array is rearranged according to the sorted index array. Then, using a simple for loop, you can sum the values of each existing index and calculate the output.
This is a grouping problem. You can use collections.defaultdict to build a dictionary mapping, incrementing values in each iteration. Then use a list comprehension:
indices = [0,1,4,2,2]
values = [5,4,3,2,1]
from collections import defaultdict
dd = defaultdict(int)
for idx, val in zip(indices, values):
dd[idx] += val
res = [dd[idx] for idx in range(max(dd) + 1)]
## functional alternative:
# res = list(map(dd.get, range(max(dd) + 1)))
print(res)
# [5, 4, 3, 0, 3]

how to find a match in a dictionary

I have two dictionaries, RFQDict and AwardsDict. I want to take the keys of RFQdict and search through AwardsDict values for matches.
So I tried this
RFQDict = {}
AwardsDict = {}
# Fetch RFQ
RFQref = db.reference('TestRFQ')
snapshot = RFQref.get()
for key, val in snapshot.items():
RFQDict[key] = val
print('{0} => {1}'.format(key, val))
Awardsref = db.reference('DibbsAwards')
dsnapshot = Awardsref.get()
for key, val in dsnapshot.items():
AwardsDict[key] = val
print('{0} => {1}'.format(key, val))
for key in RFQDict:
if key in AwardsDict.values():
print(key+ " Match found")
is this the way to do it or there is a better way and how could return the key and values where the match was found?
In python3 you can do AwardsDict.values() & RFQDict.keys() and you will get a set with the common key/values.
The '&' operator is used for set intersection and works with the dictionary views returned by values() and keys(). More information of the view returned by those methods: https://docs.python.org/3/library/stdtypes.html?highlight=dictview#dictionary-view-objects
If you want to store the keys and values that match, it would probably be best to store the key and value from the second dictionary since if you just store the matching key and value you will have elements like (a, a) which won't really tell you much about where they matched in the second dictionary. Maybe something like this
d1 = {'a': 1, 'b': 2, 'c': 3}
d2 = {'x': 'a', 'y': 1, 'z': 'c'}
res = [(i, {j: d2[j]}) for i in d1 for j in d2 if i == d2[j]]
print(res)
# [('a': {'x': 'a'}), ('c': {'z': 'c'})]
I would do a list comprehension:
result=[x for x in AwardsDict.values() if x in RFQDict.keys() ]
This way you get a list keeping the duplicates. That is, if a RFQ key is presented in more than one value in AwardsDict. With the & operator you loss that information (as sets only have unique elements).
For example:
RFQDict = {}
AwardsDict = {}
for i in range(5):
RFQDict[i]=0
for i in range(5):
AwardsDict[i]=i
for i in range(5,11):
AwardsDict[i]=i//2 #integer division, i=8 and i=9 get a value of 4
result=[x for x in AwardsDict.values() if x in RFQDict.keys() ]
print('{}'.format(result))
#output [0, 1, 2, 3, 4, 2, 3, 3, 4, 4]

Python - Get key of specific tuple index minimum in dictionary of tuples

I have a dict of tuples such as:
d = {'a': (3, 5), 'b': (5, 8), 'c': (9, 3)}
I want to return the key of the minimum of the tuple values based on the tuple index. For example, if using tuple index = 0, then 'a' would be returned. if index = 1, then 'c' would be returned. I have tried using min(), for example
min(d, key=d.get)
but am not sure how to manipulate it to select the tuple index to use. Although there are similar questions, I have not found an answer to this. Apologies in advance if this is a duped question, and please link to the answer. Thanks
You can write a lambda function to get the elements from the value by their index:
min(d, key=lambda k: d[k][0])
# 'a'
min(d, key=lambda k: d[k][1])
# 'c'
Since multiple keys could have the same value, you might want to return a list of matching keys, not just a single key.
def min_keys(d, index):
# Initialize lists
values = []
matches = []
# Append tuple items to list based on index
for t in list(d.values()):
values.append(t[index])
# If the item matches the min, append the key to list
for key in d:
if d[key][index] == min(values):
matches.append(key)
# Return a list of all keys with min value at index
return matches
Dictionaries are unsorted and have no index.
If you want the return the key alphabetically first you could use the ascii order:
print(chr(min([ord(key) for key in d.keys()])))
Here's a portable method you can use for dicts with a structure like yours, and feel free to choose the index of interest in the tuple:
def extract_min_key_by_index(cache, index):
min_val = float('inf')
min_key = 0
for k, v in d.iteritems():
if v[index] < min_val:
min_key, min_val = k, v[index]
return min_key
d = {'a': (3, 5), 'b': (5, 8), 'c': (9, 3)}
INDEX = 0
print extract_min_key_by_index(d, INDEX)

comparing list of tuple elements python

I have a two list of tuples
t1 = [ ('a',3,4), ('b',3,4), ('c',4,5) ]
t2 = [ ('a',4,6), ('c',3,4), ('b',3,6), ('d',4,5) ]
Such that
the order of the tuples may not be the same order and
the lists may not contain the same amount of tuple elements.
My goal is to compare the two lists such that if the string element matches, then compare the last integer element in the tuple and return a list containing -1 if t1[2] < t2[2], 0 if they are equal and 1 if they are greater than.
I've tried different variations but the problem i have is finding a way to match the strings to do proper comparison.
return [diff_unique(x[2],y[2]) for x,y in zip(new_list,old_list) ]
Where diff_unique does the aforementioned comparison of the integers, and new_list is t1 and old_list is t2.
I've also tried this:
return [diff_unique(x[2],y[2]) for x,y in zip(new_list,old_list) if(x[0]==y[0]]
What I intend to do is use the returned list and create a new four-tuple list with the original t1 values along with the difference from the matching t2 tuple. i.e
inc_dec_list = compare_list(new,old)
final_list = [ (f,r,u,chge) for (f,r,u), chge in zip(new,inc_dec_list)]
Where new = t1 and old = t2. This may have been an important detail, sorry I missed it.
Any help in the right direction?
Edit: I have added my test case program that mimicks what my original intent is for those who want to help. Thank you all.
import os
import sys
old = [('a',10,1),('b',10,2),('c',100,4),('d',200,4),('f',45,2)]
new = [('a',10,2),('c',10,2),('b',100,2),('d',200,6),('e',233,4),('g',45,66)]
def diff_unique(a,b):
print "a:{} = b:{}".format(a,b)
if a < b:
return -1
elif a==b:
return 0
else:
return 1
def compare_list(new_list, old_list):
a = { t[0]:t[1:] for t in new_list }
b = { t[0]:t[1:] for t in old_list }
common = list( set(a.keys())&set(b.keys()))
return [diff_unique(a[key][1], b[key][1]) for key in common]
#get common tuples
#common = [x for x,y in zip(new_list,old_list) if x[0] == y[0] ]
#compare common to old list
#return [diff_unique(x[2],y[2]) for x,y in zip(new_list,old_list) ]
inc_dec_list = compare_list(new,old)
print inc_dec_list
final_list = [ (f,r,u,chge) for (f,r,u), chge in zip(new,inc_dec_list)]
print final_list
To match the tuples by string from different lists, you can use dict comprehension (order inside the tuples is preserved):
a = {t[0]:t[1:] for t in t1} # {'a': (3, 4), 'c': (4, 5), 'b': (3, 4)}
b = {t[0]:t[1:] for t in t1} # {'a': (4, 6), 'c': (3, 4), 'b': (3, 6), 'd': (4, 5)}
Then you can iterate over the keys of both dictionaries and do the comparison. Assuming you only want to do the comparison for keys/tuples present in t1 and t2, you can join the keys using sets:
common_keys = list(set(a.keys())&set(b.keys()))
And finally compare the dictionary's items and create the list you want like this:
return [diff_unique(a[key][1],b[key][1]) for key in common_keys ]
If you need the output in the order of the alphabetically sorted characters, use the sorted function on the keys:
return [diff_unique(a[key][1],b[key][1]) for key in sorted(common_keys) ]
If you want all keys to be considered, you can do the following:
all_keys = list(set(a.keys()+b.keys()))
l = list()
for key in sorted(all_keys):
try:
l.append(diff_unique(a[key][1],b[key][1]))
except KeyError:
l.append("whatever you want")
return l
With the new information about what values should be returned in what order, the solution would be this:
ordered_keys = [t[0] for t in t1]
a = {t[0]:t[1:] for t in t1} # {'a': (3, 4), 'c': (4, 5), 'b': (3, 4)}
b = {t[0]:t[1:] for t in t1} # {'a': (4, 6), 'c': (3, 4), 'b': (3, 6), 'd': (4, 5)}
l = list()
for key in sorted(ordered_keys):
try:
l.append(diff_unique(a[key][1],b[key][1]))
except KeyError:
l.append(0) # default value
return l
First, build a default dictionary from each list, with the default value for a nonexistent key being a tuple whose last element is the smallest possible value for a comparison.
SMALL = (-float['inf'],)
from collections import defaultdict
d1 = defaultdict(lambda: SMALL, [(t[0], t[1:]) for t in t1])
d2 = defaultdict(lambda: SMALL, [(t[0], t[1:]) for t in t2])
Next, iterate over the keys in each dictionary (which can be created easily with itertools.chain). You probably want to sort the keys for the resulting list to have any meaning (otherwise, how do you know which keys produced which of -1/0/1?)
from itertools import chain
all_keys = set(chain(d1, d2))
result = [cmp(d1[k][-1], d2[k][-1]) for k in sorted(all_keys)]
Here is a simple solution of your problem,
It is not one line as you tried. I hope it will still help you
for a in t1:
for b in t2:
if a[0] != b[0]:
continue
return cmp(a[-1], b[-1])
In python 3.x, you can compare two lists of tuples
a and b thus:
import operator
a = [(1,2),(3,4)]
b = [(3,4),(1,2)]
# convert both lists to sets before calling the eq function
print(operator.eq(set(a),set(b))) #True

Categories

Resources