Related
I want to create a new value for a new list from n-concatenated values of a dictionary, as strange as it sounds I want something as described below.
I have a dictionary like this:
{'A': 9, 'B': 1, 'C': 2, 'D': 7, 'E': 6, 'F': 8, 'G': 5, 'H': 3, 'I': 4}
{'A': 9, 'B': 1, 'C': 2, 'D': 5, 'E': 3, 'F': 4, 'G': 7, 'H': 6, 'I': 8}
{'A': 7, 'B': 6, 'C': 8, 'D': 9, 'E': 1, 'F': 2, 'G': 5, 'H': 3, 'I': 4}
{'A': 7, 'B': 6, 'C': 8, 'D': 5, 'E': 3, 'F': 4, 'G': 9, 'H': 1, 'I': 2}
{'A': 5, 'B': 3, 'C': 4, 'D': 7, 'E': 6, 'F': 8, 'G': 9, 'H': 1, 'I': 2}
{'A': 5, 'B': 3, 'C': 4, 'D': 9, 'E': 1, 'F': 2, 'G': 7, 'H': 6, 'I': 8}
and I want the result as a new list, for example my_list[0] = ABC values , my_list[1] = DEF values and so on which will be displayed as 912, 768, 534 for the first row of my dictionary. The sorting does matter, it must remain as it is.
I am new to Python 3.x and I cannot find something similar to this problem. All I have achieved is to print the values only, one after another with the below script:
res_list = {frozenset(item.items()) : item for item in my_dictionary}.values()
for x in solutions:
for elem in x.keys():
print(x[elem])
Can I iterate the values and concat them per 3 steps? My goal here is to create a list of 3 digit numbers and compare these values for duplicates so that the result will be in my case just 3 distinct numbers that the sorting here does not matter.
912, 768, 345
I understand that your question may be schematic and so your dictionary keys may not actually be 'A', 'B', 'C' etc.
But given that proviso, does this help?
>>> mydict = {'A': 9, 'B': 1, 'C': 2, 'D': 7, 'E': 6, 'F': 8, 'G': 5, 'H': 3, 'I': 4}
>>> mylist = [int(''.join(str(mydict[k]) for k in group)) for group in ('ABC','DEF','GHI')]
>>> mylist
[912, 768, 534]
I have 2 array of objects:
a = [{'a': 1, 'b': 2}, {'c': 3, 'd': 4}, {'e': 5, 'f': 6}]
b = [{'a': 1, 'b': 2}, {'g': 3, 'h': 4}, {'f': 6, 'e': 5}]
Output:
a - b = [{'c': 3, 'd': 4}] ("-" symbol is only for representation, showing difference. Not mathematical minus.)
b - a = [{'g': 3, 'h': 4}]
In every array, the order of key may be different. I can try following and check for that:
for i in range(len(a)):
current_val = a[i]
for x, y in current_val.items:
//search x keyword in array b and compare it with b
but this approach doesn't feel right. Is there simpler way to do this or any utility library which can do this similar to fnc or pydash?
You can use lambda:
g = lambda a,b : [x for x in a if x not in b]
g(a,b) # a-b
[{'c': 3, 'd': 4}]
g(b,a) # b-a
[{'g': 3, 'h': 4}]
Just test if all elements are in the other array
a = [{'a': 1, 'b': 2}, {'c': 3, 'd': 4}, {'e': 5, 'f': 6}]
b = [{'a': 1, 'b': 2}, {'g': 3, 'h': 4}, {'f': 6, 'e': 5}]
def find_diff(array_a, array_b):
diff = []
for e in array_a:
if e not in array_b:
diff.append(e)
return diff
print(find_diff(a, b))
print(find_diff(b, a))
the same with list comprehension
def find_diff(array_a, array_b):
return [e for e in array_a if e not in array_b]
here is the code for subtracting list of dictionaries
a = [{'a': 1, 'b': 2}, {'c': 3, 'd': 4}, {'e': 6, 'f': 6}]
b = [{'a': 1, 'b': 2}, {'g': 3, 'h': 4}, {'f': 6, 'e': 6}]
a_b = []
b_a = []
for element in a:
if element not in b:
a_b.append( element )
for element in b:
if element not in a:
b_a.append( element )
print("a-b =",a_b)
print("b-a =",b_a)
If I have many dictionaries that I would like to modify (e.g., to filter out some value in all of them), how can I proceed in a efficient/pythonic way?
In the following example, the filtering operation within the loop works, but the actual dictionaries are not changed/affected:
d1 = {key:val for key, val in zip(('a', 'b', 'c', 'd', 'e'), range(5))}
d2 = {key:val for key, val in zip(('a', 'b', 'c', 'd', 'e'), range(4, 9))}
for d in (d1, d2):
print d
d = {key: d[key] for key in d if d[key] != 4}
print d
print d1
print d2
# {'a': 0, 'c': 2, 'b': 1, 'e': 4, 'd': 3}
# {'a': 0, 'c': 2, 'b': 1, 'd': 3}
# {'a': 4, 'c': 6, 'b': 5, 'e': 8, 'd': 7}
# {'c': 6, 'b': 5, 'e': 8, 'd': 7}
# {'a': 0, 'c': 2, 'b': 1, 'e': 4, 'd': 3}
# {'a': 4, 'c': 6, 'b': 5, 'e': 8, 'd': 7}
This should do the trick:
d1 = {key:val for key, val in zip(('a', 'b', 'c', 'd', 'e'), range(5))}
d2 = {key:val for key, val in zip(('a', 'b', 'c', 'd', 'e'), range(4, 9))}
dicts = [d1, d2]
print dicts
#[{'a': 0, 'c': 2, 'b': 1, 'e': 4, 'd': 3}, {'a': 4, 'c': 6, 'b': 5, 'e': 8, 'd': 7}]
for i, d in enumerate(dicts):
for k, v in d.items():
if v == 4:
del dicts[i][k]
print dicts
#[{'a': 0, 'c': 2, 'b': 1, 'd': 3}, {'c': 6, 'b': 5, 'e': 8, 'd': 7}]
print d1
#{'a': 0, 'b': 1, 'c': 2, 'd': 3}
print d2
#{'b': 5, 'c': 6, 'd': 7, 'e': 8}
I have 2 lists like this:
l1 = [{'a': 1, 'b': 2, 'c': 3, 'd': 4}, {'a': 5, 'b': 6, 'c': 7, 'd': 8}]
l2 = [{'a': 5, 'b': 6, 'e': 100}, {'a': 1, 'b': 2, 'e': 101}]
and I want to obtain a list l3, which is a join of l1 and l2 where values of 'a' and 'b' are equal in both l1 and l2
i.e.
l3 = [{'a': 1, 'b: 2, 'c': 3, 'd': 4, 'e': 101}, {'a': 5, 'b: 6, 'c': 7, 'd': 8, 'e': 100}]
How can I do this?
You should accumulate the results in a dictionary. You should use the values of 'a' and 'b' to form a key of this dictionary
Here, I have used a defaultdict to accumulate the entries
l1 = [{'a': 1, 'b': 2, 'c': 3, 'd': 4}, {'a': 5, 'b': 6, 'c': 7, 'd': 8}]
l2 = [{'a': 5, 'b': 6, 'e': 100}, {'a': 1, 'b': 2, 'e': 101}]
from collections import defaultdict
D = defaultdict(dict)
for lst in l1, l2:
for item in lst:
key = item['a'], item['b']
D[key].update(item)
l3 = D.values()
print l3
output:
[{'a': 1, 'c': 3, 'b': 2, 'e': 101, 'd': 4}, {'a': 5, 'c': 7, 'b': 6, 'e': 100, 'd': 8}]
Simple list operations would do the thing for you as well:
l1 = [{'a': 1, 'b': 2, 'c': 3, 'd': 4}, {'a': 5, 'b': 6, 'c': 7, 'd': 8}]
l2 = [{'a': 5, 'b': 6, 'e': 100}, {'a': 1, 'b': 2, 'e': 101}]
l3 = []
for i in range(len(l1)):
for j in range(len(l2)):
if l1[i]['a'] == l2[j]['a'] and l1[i]['b'] == l2[j]['b']:
l3.append(dict(l1[i]))
l3[i].update(l2[j])
My approach is to sort the the combined list by the key, which is keys a + b. After that, for each group of dictionaries with similar key, combine them:
from itertools import groupby
def ab_key(dic):
return dic['a'], dic['b']
def combine_lists_of_dicts(list_of_dic1, list_of_dic2, keyfunc):
for key, dic_of_same_key in groupby(sorted(list_of_dic1 + list_of_dic2, key=keyfunc), keyfunc):
combined_dic = {}
for dic in dic_of_same_key:
combined_dic.update(dic)
yield combined_dic
l1 = [{'a': 1, 'b': 2, 'c': 3, 'd': 4}, {'a': 5, 'b': 6, 'c': 7, 'd': 8}]
l2 = [{'a': 5, 'b': 6, 'e': 100}, {'a': 1, 'b': 2, 'e': 101}]
for dic in combine_lists_of_dicts(l1, l2, ab_key):
print dic
Discussion
The function ab_key returns a tuple of value for key a and b, used for sorting a groupping
The groupby function groups all the dictionaries with similar keys together
This solution is less efficient than that of John La Rooy, but should work fine for small lists
One can achieve a nice and quick solution using pandas.
l1 = [{'a': 1, 'b': 2, 'c': 3, 'd': 4}, {'a': 5, 'b': 6, 'c': 7, 'd': 8}]
l2 = [{'a': 5, 'b': 6, 'e': 100}, {'a': 1, 'b': 2, 'e': 101}]
import pandas as pd
pd.DataFrame(l1).merge(pd.DataFrame(l2), on=['a','b']).to_dict('records')
I have 2 lists of python dicts: realList and expectedList
I want realList to be considered equal to expectedList if there is one, and only one, "sub-dict" on realList for each dict of expectedList
By sub-dict I mean a dict with at least the same key/values, but which might have additional key/values.
so, for example:
realDict = [{'a': 1, 'b': 2}, {'a': 2, 'b': 3}]
==
expectedDict = [{'a': 1}, {'a': 2, 'b': 3}]
realDict = [{'a': 1, 'b': 2}, {'a': 2, 'b': 3}]
!=
expectedDict = [{'a': 2}, {'a': 2, 'b': 3}]
realDict = [{'a': 1, 'b': 2}, {'a': 1, 'b': 3}]
!=
expectedDict = [{'a': 1}]
Any modules to help? Only idea I can think of is iterating over expectedDict and removing a dict from it and from realDict whenever they match. Then, in the end, both must be [].
This works, but I'm unsure how performant it is:
def complete_subset(real_list, expected_list):
real_set_list = [set(d.items()) for d in real_list]
expected_set_list = [set(d.items()) for d in expected_list]
while len(real_set_list):
real_len = len(real_set_list)
i = 0
for real_set in real_set_list:
for expected_set in expected_set_list:
if not len(expected_set - real_set):
real_set_list.remove(real_set)
expected_set_list.remove(expected_set)
i = i + 1
if i == real_len:
break
return (not len(real_set_list)) and (not len(expected_set_list))
Here are my tests:
print complete_subset([{'a': 1, 'b': 2}, {'a': 2, 'b': 3}], [{'a': 1}, {'a': 2, 'b': 3}]) == True
print complete_subset([{'a': 1, 'b': 2}, {'a': 2, 'b': 3}], [{'a': 2}, {'a': 2, 'b': 3}]) == False
print complete_subset([{'a': 1, 'b': 2}, {'a': 2, 'b': 3}], [{'a': 1}]) == False
print complete_subset([{'a': 1, 'b': 2}, {'a': 1, 'b': 2}], [{'a': 1}, {'b': 2}]) == True
print complete_subset([
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7, 'h': 8, 'i': 9, 'j': 10},
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7, 'h': 8, 'i': 9, 'j': 10},
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7, 'h': 8, 'i': 9, 'j': 10},
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7, 'h': 8, 'i': 9, 'j': 10},
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7, 'h': 8, 'i': 9, 'j': 10},
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7, 'h': 8, 'i': 9, 'j': 10},
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7, 'h': 8, 'i': 9, 'j': 10},
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7, 'h': 8, 'i': 9, 'j': 10},
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7, 'h': 8, 'i': 9, 'j': 10},
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7, 'h': 8, 'i': 9, 'j': 10},
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7, 'h': 8, 'i': 9, 'j': 10},
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7, 'h': 8, 'i': 9, 'j': 10},
], [
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7, 'h': 8, 'i': 9},
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7, 'h': 8},
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7},
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6},
{'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5},
{'a': 1, 'b': 2, 'c': 3, 'd': 4},
{'a': 1, 'b': 2, 'c': 3},
{'a': 1, 'b': 2},
{'a': 1},
{'a': 1, 'c': 3, 'd': 4, 'f': 6, 'g': 7, 'h': 8, 'i': 9, 'j': 10},
{'a': 1, 'b': 2, 'c': 3, 'e': 5, 'f': 6, 'h': 8, 'i': 9, 'j': 10},
{'a': 1, 'b': 2, 'd': 4, 'e': 5, 'g': 7, 'h': 8, 'j': 10},
]) == True
In case your two lists are to be compared element by element, you can do it this way.
def compare(realDict, expectedDict):
if len(readDict) != len(expectedDict):
return False
for d1, d2 in zip(realDict, expectedDict):
for key in d2:
if key not in d1 or d1[key] != d2[key]:
return False
return True