Iterate over a list of objects getting ke/value pairs - python

I'd like to iterate over a list of objects (where I don't know their keys) in as simple way as possible, without creating unnecessary temp variables.
So let's say that's my array :
y = [{'faz': 'baz'}, {'foo': 'bar'}]
Getting k, v from object can be easily done with iteritems() but is it possible to iterate over list using lambda at the same time ?
EDIT
Pseudocode:
for k, v in x where x is an array item

if your keys are unique across the list, you can do:
for k, v in {k:v for l in y for k, v in l.iteritems()}.iteritems():
print k, v
or equivalently,
y2 = {k:v for l in y for k, v in l.iteritems()}
for k, v in y2.iteritems():
print k, v
but it is not very pretty.
If all your dict have one one key-value pair, you can do this:
for k,v in map(lambda x: x.items()[0], y):
print k, v
Another solution is the following which just iterates over the list and then over the dict:
def items(lis):
for l in lis:
for k, v in l.iteritems():
yield k, v
for k, v in items(y):
print k, v

Related

Extract differences of values of 2 given dictionaries - values are tuples of strings

I have two dictionaries as follows, I need to extract which strings in the tuple values are in one dictionary but not in other:
dict_a = {"s": ("mmmm", "iiiii", "p11"), "yyzz": ("oo", "i9")}
dict_b = {"s": ("mmmm",), "h": ("pp",), "g": ("rr",)}
The desired output:
{"s": ("iiiii", "p11"), "yyzz": ("oo", "i9")}
The order of the strings in the output doesn't matter.
One way that I tried to solve, but it doesn't produce the expected result:
>>> [item for item in dict_a.values() if item not in dict_b.values()]
[('mmmm', 'iiiii', 'p11'), ('oo', 'i9')]
If order doesn't matter, convert your dictionary values to sets, and subtract these:
{k: set(v) - set(dict_b.get(k, ())) for k, v in dict_a.items()}
The above takes all key-value pairs from dict_a, and for each such pair, outputs a new dictionary with those keys and a new value that's the set difference between the original value and the corresponding value from dict_b, if there is one:
>>> dict_a = {"s": ("mmmm", "iiiii", "p11"), "yyzz": ("oo", "i9")}
>>> dict_b = {"s": ("mmmm",), "h": ("pp",), "g": ("rr",)}
>>> {k: set(v) - set(dict_b.get(k, ())) for k, v in dict_a.items()}
{'s': {'p11', 'iiiii'}, 'yyzz': {'oo', 'i9'}}
The output will have sets, but these can be converted back to tuples if necessary:
{k: tuple(set(v) - set(dict_b.get(k, ()))) for k, v in dict_a.items()}
The dict_b.get(k, ()) call ensures there is always a tuple to give to set().
If you use the set.difference() method you don't even need to turn the dict_b value to a set:
{k: tuple(set(v).difference(dict_b.get(k, ()))) for k, v in dict_a.items()}
Demo of the latter two options:
>>> {k: tuple(set(v) - set(dict_b.get(k, ()))) for k, v in dict_a.items()}
{'s': ('p11', 'iiiii'), 'yyzz': ('oo', 'i9')}
>>> {k: tuple(set(v).difference(dict_b.get(k, ()))) for k, v in dict_a.items()}
{'s': ('p11', 'iiiii'), 'yyzz': ('oo', 'i9')}
{k: [v for v in vs if v not in dict_b.get(k, [])] for k,vs in dict_a.items()}
if you want to use tuples (or sets - just replace the cast)
{k: tuple(v for v in vs if v not in dict_b.get(k, [])) for k,vs in dict_a.items()}
Try this (see comments for explanations):
>>> out = {} # Initialise output dictionary
>>> for k, v in dict_a.items(): # Iterate through items of dict_a
... if k not in dict_b: # Check if the key is not in dict_b
... out[k] = v # If it isn't, add to out
... else: # Otherwise
... out[k] = tuple(set(v) - set(dict_b[k])) # Subtract sets to find the difference
...
>>> out
{'s': ('iiiii', 'p11'), 'yyzz': ('oo', 'i9')}
This can then be simplified using a dictionary comprehension:
>>> out = {k: tuple(set(v) - set(dict_b.get(k, ()))) for k, v in dict_a.items()}
>>> out
{'s': ('iiiii', 'p11'), 'yyzz': ('oo', 'i9')}
See this solution :
First iterate through all keys in dict_a
Check if the key is present or not in dict_b
Now, if present: take the tuples and iterate through dict_a's tuple(as per your question). now check weather that element is present or not in dict_b's tuple. If it is present just leave it. If it is not just add that element in tup_res.
Now after the for loop, add that key and tup value in the dict_res.
if the key is not present in dict_b simply add it in dict_res.
dict_a = {"s":("mmmm","iiiii","p11"), "yyzz":("oo","i9")}
dict_b = {"s":("mmmm"),"h":("pp",),"g":("rr",)}
dict_res = {}
for key in dict_a:
if key in dict_b:
tup_a = dict_a[key]
tup_b = dict_b[key]
tup_res = ()
for tup_ele in tup_a:
if tup_ele in tup_b:
pass
else:
tup_res = tup_res + (tup_ele,)
dict_res[key] = tup_res;
else:
dict_res[key] = dict_a[key];
print(dict_res)
It is giving correct output :)

A basic operation of python's dictionary

encoder.load_state_dict({k:v for k,v in encoder_dict.items() if k in model_dict})
This syntax is an operation of the dictionary, but I can't understand that what does "k:v" acts?
encoder.load_state_dict({k:v for k,v in encoder_dict.items() if k in model_dict})
This is dictionary comprehension. An equivalent code in simple terms would be:
new_dict = dict()
for k,v in encoder_dict.items():
if k in model_dict:
new_dict[k] = v
encoder.load_state_dict(new_dict)
where k and v corresponds to the key and value pair returned by encoder_dict.items()

Deleting values in a dictionary containing substring in Python

I have a dictionary that contains several values (filepaths) belonging to the same key, for a specific task. I want to delete any dictionary values that contain "Converted" within the filepath. This is because I only want to retain the values from the "Submitted" folder.
I have tried several attempts to write something that would do this but there are *not any examples online. Any help in providing some code to do this task would be much appreciated.
# Create empty dictionary
d = dict()
# Add elements containing multiple values per key
d["key1"] = ["C:/Users/TAS/Documents/Folder/Converted/script.py"]
d["key1"].append("C:/Users/TAS/Documents/Folder/Submitted/script.py")
d["key2"] = ["C:/Users/TAS/Documents/Folder/Converted/script2.py"]
d["key2"].append("C:/Users/TAS/Documents/Folder/Submitted/script2.py")
# key1,key2
d.keys()
# Filepaths
d.values()
# We want to remove any values from the dictionary containing "Converted" within the filepath
d2 = {k:v for k,v in d.items() if v !='*Converted'}
You're almost there. Regular python strings do not support wildcard so you're doing strict match with '*Converted'.
If you want to do it by dict comprehension:
d2 = {k: list(filter(lambda x: 'Converted' not in x, v)) for k, v in d.items()}
Regular looping with filter:
for k, v in d.items():
d[k] = list(filter(lambda x: 'Converted' not in x, v)
Regular looping with list comprehension.
for k, v in d.items():
d[k] = [path_ for path_ in v if 'Converted' not in path_]

Check if value exists in a dictionary of dictionaries and get the key(s)?

I have a dictionary of dictionaries:
x = {'NIFTY': {11382018: 'NIFTY19SEPFUT', 13177346: 'NIFTY19OCTFUT', 12335874: 'NIFTY19NOVFUT'}}
The dictionary has a lot of other dictionaries inside.
I want to check whether example:
y = 11382018
exists in the dictionary, if yes, get the master key in this case NIFTY and the value of the above key i.e. 'NIFTY19SEPFUT'
I can do this in the following way I assume:
for key in x.keys():
di = x[key]
if y in di.keys():
inst = key
cont = di[y]
Just wondering if there is a better way.
I was thinking along the lines of not having to loop over the entire dictionary master keys
A more compact way to retrieve both values of interest would be using a nested dictionary comprehension:
[(k, sv) for k,v in x.items() for sk,sv in v.items() if sk == y]
# [('NIFTY', 'NIFTY19SEPFUT')]
More compact version (generic):
[(k, v[y]) for k, v in d.items() if y in v]
Or:
*next(((k, v[y]) for k, v in d.items() if y in v), 'not found')
if you can guarantee the key is found only in one nested dictionary. (Note that I have used d as dictionary here, simply because that feels more meaningful)
Code:
d = {'NIFTY': {11382018: 'NIFTY19SEPFUT', 13177346: 'NIFTY19OCTFUT', 12335874: 'NIFTY19NOVFUT'}}
y = 11382018
print([(k, v[y]) for k, v in d.items() if y in v])
# or:
# print(*next(((k, v[y]) for k, v in d.items() if y in v), 'not found'))
Straightforwardly (for only 2 levels of nesting):
x = {'NIFTY': {11382018: 'NIFTY19SEPFUT', 13177346: 'NIFTY19OCTFUT', 12335874: 'NIFTY19NOVFUT'}}
search_key = 11382018
parent_key, value = None, None
for k, inner_d in x.items():
if search_key in inner_d:
parent_key, value = k, inner_d[search_key]
break
print(parent_key, value) # NIFTY NIFTY19SEPFUT

Iterating through a python dictionary with lists as values

I'm trying to iterate through a dictionary that looks like:
d = {
"list_one": [
"hello",
"two",
"three"
],
"list_two": [
"morning",
"rain"
]
}
I'm using the function:
def combine_words(d):
for k, v in d.items():
a = {k: ("|".join(v))}
return a
When I run this with print, my output is just one key, value pair. I'm not sure what is happening here. My ideal out put would be:
{
'list_one': 'hello|two|three',
'list_two': 'morning|rain'
}
def combine_words(d):
for k, v in d.items():
a = {k: ("|".join(v))}
return a
This constantly reassigns the dictionary to a, and isn't combining the results
def combine_words(d):
a = {}
for k, v in d.items():
a[k] = ("|".join(v))
return a
Would keep adding new entries to the dictionary
a gets replaced by a new dict each time through your loop. You want a dict comprehension.
def combine_words(d):
return {k: "|".join(v) for k, v in d.items()}
The problem is that you change the value of a during every iteration of your for loop because you reassign a. You can modify your code to get around this:
for k, v in d.items():
a[k] = "|".join(v)
Alternatively, you can use a dict comprehension:
return {k: "|".join(v) for k, v in d.items()}

Categories