how to make values of a key of a dic uniqe? - python

I have a list of dic. the value contains some results. I want to uniq them. (some of them are repetitive)
Example of dic[0]:
{'key': 'art director',
'Results': [{'actor': 1},
{'art director': 4},
{'creative designer': 2},
{'art director': 4},
{'creative designer': 2},
{'digital designer': 1},
{'graphic designer': 1},
{'communications consultant': 1},
{'designer': 1},
{'art director': 4},
{'art director': 4}]}
output:
{'key': 'art director',
'Results': [{'actor': 1},
{'art director': 4},
{'creative designer': 2},
{'digital designer': 1},
{'graphic designer': 1},
{'communications consultant': 1},
{'designer': 1},
]}
I wanted to use loop and use the following if condition:
if dic[i]['Results'][k]==dic[i]['Results'][j]
but it is not efficient at all. since there are 3 indices. any better way?

You could use a dictionary for your "Results" values rather than a list of single key dictionaries. So the following:
{
'key': 'art director',
'Results': [
{'actor': 1},
{'art director': 4},
{'creative designer': 2},
{'art director': 4},
{'creative designer': 2},
{'digital designer': 1},
{'graphic designer': 1},
{'communications consultant': 1},
{'designer': 1},
{'art director': 4},
{'art director': 4}
]
}
becomes
import pprint
pprint.pprint({
'key': 'art director',
'Results': {
'actor': 1,
'art director': 4,
'creative designer': 2,
'art director': 4,
'creative designer': 2,
'digital designer': 1,
'graphic designer': 1,
'communications consultant': 1,
'designer': 1,
'art director': 4,
'art director': 4
}
})
Since dictionaries can only have one value per key, this will automatically handle deduplication as you build the Results dictionary.

You can use this line, in order to take the whole list (The value of the key 'Result') and check for duplicates, then change it accordingly if it is already inside your key.
d['Results'] = [dict(t) for t in {tuple(d.items()) for d in d['Results']}]

I have two solutions.
Solution 1
This first one will output exactly what you pretended:
res = [] # represents the final results list
aux = {} # used to check if the key is already in 'Results': []
for i in dic:
for r in i['Results']:
for k,v in r.items():
if k not in aux.keys():
aux[k] = v
res.append({k:v})
i['Results'] = res
print(dic)
Solution 2
This second one will transform 'Results' value in dic[I] into a single dictionary instead of a list of dictionaries:
res = {}
for i in dic:
for r in i['Results']:
for k,v in r.items():
res[k] = v
i['Results'] = res
print(dic)
Using your input as an example:
Output:
[{'Results': {'actor': 1,
'art director': 4,
'communications consultant': 1,
'creative designer': 2,
'designer': 1,
'digital designer': 1,
'graphic designer': 1},
'key': 'art director'}]
Sample dic:
dic = [{'key': 'art director',
'Results': [{'actor': 1},
{'art director': 4},
{'creative designer': 2},
{'art director': 4},
{'creative designer': 2},
{'digital designer': 1},
{'graphic designer': 1},
{'communications consultant': 1},
{'designer': 1},
{'art director': 4},
{'art director': 4}]}]

Related

Variable Locality

I'm trying to implement Dijkstra alogorthim. While doing so, I've coded graph part.
I'm observing this strange output. Not sure which feature causing this. I'm getting same output for two print though one is local variable and another is in class.
class Graph(object):
def __init__(self, nodes, init_graph):
self.nodes = nodes
self.graph = self.construct_graph(nodes, init_graph)
def construct_graph(self, nodes, init_graph):
'''
This method makes sure that the graph is symmetrical.
In other words, if there's a path from node A to B with a value V, there needs to be a path from node B to node A with a value V.
:param self:
:param nodes:
:param init_graph:
:return:
'''
graph = {}
for node in nodes:
graph[node] = {}
graph.update(init_graph)
for node, edges in graph.items():
for adjacent_node, value in edges.items():
if graph[adjacent_node].get(node, False) == False:
graph[adjacent_node][node] = value
print(graph)
return graph
if __name__=="__main__":
nodes = ["Reykjavik", "Oslo", "Moscow", "London", "Rome", "Berlin", "Belgrade", "Athens"]
init_graph = {}
for node in nodes:
init_graph[node] = {}
init_graph["Reykjavik"]["Oslo"] = 5
init_graph["Reykjavik"]["London"] = 4
init_graph["Oslo"]["Berlin"] = 1
init_graph["Oslo"]["Moscow"] = 3
init_graph["Moscow"]["Belgrade"] = 5
init_graph["Moscow"]["Athens"] = 4
init_graph["Athens"]["Belgrade"] = 1
init_graph["Rome"]["Berlin"] = 2
init_graph["Rome"]["Athens"] = 2
graph = Graph(nodes, init_graph)
print(init_graph)
Output :
{'Reykjavik': {'Oslo': 5, 'London': 4}, 'Oslo': {'Berlin': 1, 'Moscow': 3, 'Reykjavik': 5}, 'Moscow': {'Belgrade': 5, 'Athens': 4, 'Oslo': 3}, 'London': {'Reykjavik': 4}, 'Rome': {'Berlin': 2, 'Athens': 2}, 'Berlin': {'Oslo': 1, 'Rome': 2}, 'Belgrade': {'Moscow': 5, 'Athens': 1}, 'Athens': {'Belgrade': 1, 'Moscow': 4, 'Rome': 2}}
{'Reykjavik': {'Oslo': 5, 'London': 4}, 'Oslo': {'Berlin': 1, 'Moscow': 3, 'Reykjavik': 5}, 'Moscow': {'Belgrade': 5, 'Athens': 4, 'Oslo': 3}, 'London': {'Reykjavik': 4}, 'Rome': {'Berlin': 2, 'Athens': 2}, 'Berlin': {'Oslo': 1, 'Rome': 2}, 'Belgrade': {'Moscow': 5, 'Athens': 1}, 'Athens': {'Belgrade': 1, 'Moscow': 4, 'Rome': 2}}
Expected Output :
{'Reykjavik': {'Oslo': 5, 'London': 4}, 'Oslo': {'Berlin': 1, 'Moscow': 3, 'Reykjavik': 5}, 'Moscow': {'Belgrade': 5, 'Athens': 4, 'Oslo': 3}, 'London': {'Reykjavik': 4}, 'Rome': {'Berlin': 2, 'Athens': 2}, 'Berlin': {'Oslo': 1, 'Rome': 2}, 'Belgrade': {'Moscow': 5, 'Athens': 1}, 'Athens': {'Belgrade': 1, 'Moscow': 4, 'Rome': 2}}
{'Reykjavik': {'Oslo': 5, 'London': 4}, 'Oslo': {'Berlin': 1, 'Moscow': 3}, 'Moscow': {'Belgrade': 5, 'Athens': 4}, 'London': {}, 'Rome': {'Berlin': 2, 'Athens': 2}, 'Berlin': {}, 'Belgrade': {}, 'Athens': {'Belgrade': 1}}
graph.update(init_graph) creates references to the nested dictionaries in init_graph rather than creating a separate copy. This allows the data in init_graph to be overwritten and is causing the strange outputs.
This fixed the issue for me:
from copy import deepcopy
graph = Graph(nodes, deepcopy(init_graph))
Here's some info on dictionary copying that was helpful for me: Copy a Python Dictionary: A Complete Guide

Python: How to sum values from a 3d array, where the last array is a dictionary using functional map and sum

(This is Advent Of Code day 4, I already have my stars, but I'd like to do it more efficiently)
I have a 3d matrix like this one:
[
[
[{22: 0}, {13: 0}, {17: 1}, {11: 1}, {0 : 1}],
[{8 : 0}, {2 : 1}, {23: 1}, {4 : 1}, {24: 1}],
[{21: 1}, {9 : 1}, {14: 1}, {16: 0}, {7 : 1}],
[{6 : 0}, {10: 0}, {3 : 0}, {18: 0}, {5 : 1}],
[{1 : 0}, {12: 0}, {20: 0}, {15: 0}, {19: 0}]
],
[
[{3 : 0}, {15: 0}, {0 : 1}, {2 : 1}, {22: 0}],
[{9 : 1}, {18: 0}, {13: 0}, {17: 1}, {5 : 1}],
[{19: 0}, {8 : 0}, {7 : 1}, {25: 0}, {23: 1}],
[{20: 0}, {11: 1}, {10: 0}, {24: 1}, {4 : 1}],
[{14: 1}, {21: 1}, {16: 0}, {12: 0}, {6 : 0}]
],
[
[{14: 1}, {21: 1}, {17: 1}, {24: 1}, {4 : 1}],
[{10: 0}, {16: 0}, {15: 0}, {9 : 1}, {19: 0}],
[{18: 0}, {8 : 0}, {23: 1}, {26: 0}, {20: 0}],
[{22: 0}, {11: 1}, {13: 0}, {6 : 0}, {5 : 1}],
[{2 : 1}, {0 : 1}, {12: 0}, {3 : 0}, {7 : 1}]
]
]
And I want to sum all values from one of those matrices using map/sum functions.
This is what I have now and works:
# z is one of those matrices, 0, 1 or 2
soma = 0
for line in matrices[z]: # line is a list of dictionaries
for dic in line: # dic is a dictionary from the list
valor = list(dic.values())[0]
if valor == 0:
soma += list(dic.keys())[0]
What I've tried to do:
print("soma = ", sum(map(sum, ( (value.values())[0] for value in matrizes[z]))))
which doesnt work, and I get this error:
Traceback (most recent call last):
File "day4.py", line 75, in <module>
print("part 1 = ", sum(map(sum, ((value.values())[0] for value in matrizes[z]))))
File "day4.py", line 75, in <genexpr>
print("part 1 = ", sum(map(sum, ((value.values())[0] for value in matrizes[z]))))
AttributeError: 'list' object has no attribute 'values'
I've found a post with 2d arrays, but couldnt understand how to make it for 3d arrays.
I've also found posts using "numpy", but I want to do with map and sum functions.
You can do:
z = 0
soma = sum(map(lambda line: sum(k for d in line for k, v in d.items() if v == 0), matrices[z]))
print(soma) # 163
You can do one line like this:
m = [
[
[{22: 0}, {13: 0}, {17: 1}, {11: 1}, {0 : 1}],
[{8 : 0}, {2 : 1}, {23: 1}, {4 : 1}, {24: 1}],
[{21: 1}, {9 : 1}, {14: 1}, {16: 0}, {7 : 1}],
[{6 : 0}, {10: 0}, {3 : 0}, {18: 0}, {5 : 1}],
[{1 : 0}, {12: 0}, {20: 0}, {15: 0}, {19: 0}]
],
[
[{3 : 0}, {15: 0}, {0 : 1}, {2 : 1}, {22: 0}],
[{9 : 1}, {18: 0}, {13: 0}, {17: 1}, {5 : 1}],
[{19: 0}, {8 : 0}, {7 : 1}, {25: 0}, {23: 1}],
[{20: 0}, {11: 1}, {10: 0}, {24: 1}, {4 : 1}],
[{14: 1}, {21: 1}, {16: 0}, {12: 0}, {6 : 0}]
],
[
[{14: 1}, {21: 1}, {17: 1}, {24: 1}, {4 : 1}],
[{10: 0}, {16: 0}, {15: 0}, {9 : 1}, {19: 0}],
[{18: 0}, {8 : 0}, {23: 1}, {26: 0}, {20: 0}],
[{22: 0}, {11: 1}, {13: 0}, {6 : 0}, {5 : 1}],
[{2 : 1}, {0 : 1}, {12: 0}, {3 : 0}, {7 : 1}]
]
]
s = sum([k for y in m for x in y for z in x for k,v in z.items() if v == 0])
print(s)

Split a list of dictionaries into multiple chunks

I have this one list
list_dict = [
{'id': 1},
{'item': 'apple'},
{'id': 2},
{'item': 'pear'},
{'id': 1},
{'item': 'peach'},
{'id': 2},
{'item': 'kiwi'},
{'id': 3},
{'item': 'banana'},
{'id': 4},
{'item': 'mango'},
{'id': 1},
{'item': 'watermelon'},
{'id': 2},
{'item': 'plum'},
{'id': 3},
{'item': 'grapes'}]
and I want to split like this (start to make sublist when "id" is 1)
result = [
[{'id': 1},
{'item': 'apple'},
{'id': 2},
{'item': 'pear'}],
[{'id': 1},
{'item': 'peach'},
{'id': 2},
{'item': 'kiwi'},
{'id': 3},
{'item': 'banana'},
{'id': 4},
{'item': 'mango'}],
[{'id': 1},
{'item': 'watermelon'},
{'id': 2},
{'item': 'plum'},
{'id': 3},
{'item': 'grapes'}]]
Some nested for loop will work
list_dict = [{"id":1},{"item":"apple"},{"id":2},{"item":"pear"},{"id":1},{"item":"peach"},{"id":2},{"item":"kiwi"},{"id":3},{"item":"banana"},{"id":4},{"item":"mango"},{"id":1},{"item":"watermelon"},{"id":2},{"item":"plum"},{"id":3},{"item":"grapes"}]
output = []
temp = []
for i in list_dict:
if i.get('id', -1) == 1 and temp:
output.append(temp.copy())
temp.clear()
temp.append(i)
else:
temp.append(i)
output.append(temp.copy())
print(output)
#[[{'id': 1}, {'item': 'apple'}, {'id': 2}, {'item': 'pear'}], [{'id': 1}, {'item': 'peach'}, {'id': 2}, {'item': 'kiwi'}, {'id': 3}, {'item': 'banana'}, {'id': 4}, {'item': 'mango'}], [{'id': 1}, {'item': 'watermelon'}, {'id': 2}, {'item': 'plum'}, {'id': 3}, {'item': 'grapes'}]]
Maybe something like this?
main_list = []
current_list = []
for el in list_dict:
if el.get("id", 0) == 1:
if current_list:
main_list.append(current_list)
current_list = [el]
else:
current_list.append(el)
if current_list:
main_list.append(current_list)
print(main_list)

How do I split list of dict in Python?

lis_dict = [
{item: "some item"},
{quantity: 2},
{id: 10},
{quantity: 2},
{id: 11},
{quantity: 2},
{quantity: 2},
{id: 12}
]
I have above list of dict, which I would like to split into a sub-list.
result = [
[{item: "some item"}, {quantity: 2}, {id: 10}],
[{quantity: 2}, {id: 11}],
[{quantity: 2}, {quantity: 2}, {id: 12}]
]
The question asks to split the list by "id" into a nested list.
Input:
lis_dict
[{'item': 'some item'},
{'quantity': 2},
{'id': 10},
{'quantity': 2},
{'id': 11},
{'quantity': 2},
{'quantity': 2},
{'id': 12}]
Code:
result = []
s = 0
for i,j in enumerate(lis_dict):
if ("id" in j.keys()):
result.append(lis_dict[s:i+1])
s = i+1
Prints:
[[{'item': 'some item'}, {'quantity': 2}, {'id': 10}],
[{'quantity': 2}, {'id': 11}],
[{'quantity': 2}, {'quantity': 2}, {'id': 12}]]
A more general approach might be the following (in which you could add more dictionaries in a sublist):
lis_dict = [{'item': 'some item'},
{'quantity': 2},
{'id': 10},
{'quantity': 2},
{'item': 'some item'},
{'id': 11},
{'quantity': 2},
{'quantity': 2},
{'id': 12}]
result = []
sublist = []
for d in lis_dict:
sublist.append(d)
if d.get("id"):
result.append(sublist)
sublist = []
print(result)
# [[{'item': 'some item'}, {'quantity': 2}, {'id': 10}], [{'quantity': 2},
# {'item': 'some item'}, {'id': 11}], [{'quantity': 2}, {'quantity': 2}, {'id': 12}]]

Changing a Specific Value in a Matrix of Dictionaries

I want to change a specific value in a 5x5 matrix of dictionaries, here's my code:
matrix = [[{"value": 1}]*5]*5
matrix[0][0]["value"] = 4
print(matrix)
Instead of changing one value, it changes all of them:
[[{'value': 4}, {'value': 4}, {'value': 4}, {'value': 4}, {'value': 4}], [{'value': 4}, {'value': 4}, {'value': 4}, {'value': 4}, {'value': 4}], [{'value': 4}, {'value': 4}, {'value': 4}, {'value': 4}, {'value': 4}], [{'value': 4}, {'value': 4}, {'value': 4}, {'value': 4}, {'value': 4}], [{'value': 4}, {'value': 4}, {'value': 4}, {'value': 4}, {'value': 4}]]
Shouldn't the code only change one value, like this:
[[{'value': 4}, {'value': 1}, {'value': 1}, {'value': 1}, {'value': 1}], [{'value': 1}, {'value': 1}, {'value': 1}, {'value': 1}, {'value': 1}], [{'value': 1}, {'value': 1}, {'value': 1}, {'value': 1}, {'value': 1}], [{'value': 1}, {'value': 1}, {'value': 1}, {'value': 1}, {'value': 1}], [{'value': 1}, {'value': 1}, {'value': 1}, {'value': 1}, {'value': 1}]]
What do I have to change in the code to get this output?
Multiplying a list by n simply repeats its contents n times. Therefore, this
[{"value": 1}]*5
will create a new list with 5 references to the same dict {"value": 1}. Since all list items reference the same object, updating any of them affects the others.
Instead, use list comprehensions to create distinct objects:
matrix = [[{"value": 1} for _ in range(5)] for _ in range(5)]
matrix[0][0]["value"] = 4
print(matrix)

Categories