'list of dicts to list of chainmap dicts with unique keys
How to convert this
l = [{'a':1}, {'b':2}, {'a':3}, {'b':4}]
to
l_chained = [{'a':1, 'b':2}, {'a':3, 'b':4}]
I know how to fetch unique keys, but stuck with further implementation
ChainMap just makes plain dictionary excluding l[2] and l[3]
UPDATE1
I use Mapping to pass it as ORM kwargs
user_data = [{'name':'John'}, {'lastname':'Doe'}]
user_data = {'name':'John', 'lastname':'Doe'}
user = User.create(**data1_chained)
User provides FK that must be passed to related model
courses_data = [{'title':'Python'}, {'paid':0}, {'title':'Kubernetes'}, {'paid':1}]
courses_data_chained = [{'title':'Python', 'paid':0}, {'title':'Kubernetes', 'paid':1}]
for c_d_c in courses_data_chained:
Course.create(**c_d_c, user=user)
length of data is dynamic so I have to check if it has duplicated keys and generate array of dicts and than create records.
UPDATE2 First attempt still provides non generic solution, because dictionaries must go in that order, but works for arrays of various lengths
def chainmap_unique(arr:List[Dict[str, Any]]):
unique_keys:List[str] = [next(k for k in tuple(elem.keys())) for elem in arr]
deque_arr:Deque = deque(arr)
last_keys = []
output = []
container = []
while deque_arr:
key = next(k for k in tuple(deque_arr[0].keys()))
if not key in last_keys:
container.append(deque_arr[0])
deque_arr.popleft()
last_keys.append(key)
else:
if all([k in unique_keys for k in last_keys]):
d = dict(ChainMap(*container))
last_keys.clear()
container.clear()
output.append(d)
else:
continue
else:
d = dict(ChainMap(*container))
last_keys.clear()
container.clear()
output.append(d)
# assert result
return output
l1 = [{'a':1}, {'b':2}, {'c':6}, {'a':3}, {'b':4},{'c':8}]
result1 = chainmap_unique(l1)
assert result1 == [{'c': 6, 'b': 2, 'a': 1}, {'c': 8, 'b': 4, 'a': 3}]
l2 = [{'a':1}, {'b':2}, {'c':6}, {'d':9}, {'a':3}, {'b':4},{'c':8}, {'d':10}]
result2 = chainmap_unique(l2)
assert result2 == [{'d':9, 'c': 6, 'b': 2, 'a': 1}, {'d':10, 'c': 8, 'b': 4, 'a': 3}]
Solution 1:[1]
you should try something like this:
l = [{'a':1}, {'b':2}, {'a':3}, {'b':4}]
l_chained = list()
for a, b in zip(l[::2], l[1::2]):
l_chained.append({**a, **b})
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Félix Herbinet |
