I have a python dictionary that looks like this {3:[2,3,4,5],4:[3,6,7,8]}.I need to map the values in dictionary to the keys. i.e {2:[3],3:[3,4],4:[3],5:[3],6:[4],7:[4],8:[4]}.
How can I do that?
Loop through the dict and through each value list to build the new structure. You can use dict.setdefault (or a collections.defaultdict) to save yourself some boilerplate code:
data = {3: [2, 3, 4, 5], 4: [3, 6, 7, 8]}
rev = {}
for k, lst in data.items():
for val in lst:
rev.setdefault(val, []).append(k)
rev
# {2: [3], 3: [3, 4], 4: [3], 5: [3], 6: [4], 7: [4], 8: [4]}
or
from collections import defaultdict
rev = defaultdict(list)
for k, lst in data.items():
for val in lst:
rev[val].append(k)
Related
I have a python dictionary which contains multiple key,values which are actually image indexes. For e.g. the dictionary I have looks something as given below
{
1: [1, 2, 3],
2: [1, 2, 3],
3: [1, 2, 3],
4: [4, 5],
5: [4, 5],
6: [6]
}
this means that 1 is related to 1, 2 & 3. Similarly 2 is related to 1, 2 & 3. 6 has only 6 in it so it's related to none of the other elements. This is leading me to perform extra operations in my programs. I want the dictionary to be filtered and look like
# Preferred output
{
1: [2, 3],
4: [5],
6: []
}
So far I have tried
new_dict = dict()
# source is the original dictionary
for k,v in source.items():
ok = True
for k1,v1 in new_dict.items():
if k in v1: ok = False
if ok: new_dict[k] = v
This modifies the dictionary to
{1: [1, 2, 3], 4: [4, 5], 6: [6]}
I am looking for a more efficient and pythonic way to solve this problem.
This shows the preferred output:
source = {
1: [1, 2, 3],
2: [1, 2, 3],
3: [1, 2, 3],
4: [4, 5],
5: [4, 5],
6: [6]
}
new_dict = {}
seen = set()
for k, v in source.items():
if k in seen: continue
seen.add(k)
new_v = [i for i in v if i not in seen]
seen.update(new_v)
new_dict[k] = new_v
print(new_dict)
How about this, use my modification below to remove the first item in the list during each loop. I commented the line which does it.
new_dict = dict()
# source is the original dictionary
for k,v in source.items():
ok = True
for k1,v1 in new_dict.items():
if k in v1: ok = False
if ok: new_dict[k] = v[1:] #this line removes the first element.
My output is,
{1: [2, 3], 4: [5], 6: []}
your modified code:
ver 1:
new_dict = dict()
for k, v in source.items():
if not any(k in v1 for v1 in new_dict.values()):
new_dict[k] = v[1:]
ver 2:
tmp = dict()
for k, v in source.items():
tmp[tuple(v)] = tmp.get(tuple(v), []) + [k]
res = dict()
for k, v in tmp.items():
res[v[0]] = v[1:]
ver 3:
new_dict = {v[0]: list(v[1:]) for v in set(map(tuple, source.values()))}
I trying to match keys and values in a dictionary together and put them into a new dictionary.
My initial dictionary looks like this:
d = {1: [5,6], 3: [4], 8: [2,3]}
I know that I can access keys and values using d.keys() and d.values().
My goal is to find all items which relate. I think it is best explained if I illustrate my desired output.
I wish to create a new dict that gives me:
finaldict = {1: [5,6], 2: [3,4,8], 3: [2,4,8], 4:[2,3,8] 5:[1,6], 6:[1,5], 8:[2,3,4]}
That is, I want to get keys of all numbers, and give values to what number they are related to.
My attempt:
d = {1: [5,6], 3:[4],8:[2,3]}
print(d)
keys = list(d.keys())
vals = list(d.values())
for i in range(0,len(d.keys())):
current_vals = list(vals[i])
length = len(current_vals)
for v in current_vals:
if v in d.keys(): #if the dictionary exists, then append
add = [keys[i],current_vals]
d[v].append(add)
else:
add2 = [keys[i],current_vals]
empty = []
for a in add2:
if type(a) == int:
empty.append(a)
if type(a) == list:
for b in a:
empty.append(b)
d[v] = empty
keys = list(d.keys())
vals = list(d.values())
for i in range(0,len(keys)):
if keys[i] in vals[i]:
vals[i].remove(keys[i])
finaldict = {}
for j in range(0,len(keys)):
finaldict[keys[j]] = vals[j]
print("Final dict:\n",finaldict)
My attempt gives me the output
Final dict:
{1: [5, 6], 3: [4, [8, [2, 3]]], 8: [2, 3], 5: [1, 6], 6: [1, 5], 4: [3], 2: [8, 3]}
As you can see, finaldict[3] has the values [4, [8, [2, 3,]]].
The values themselves are wrong (3 should not be there), and also I want this to be a single list, and not on the format it is now. There are also other issues, such as finaldict[2] having the values [8, 3] when it should, in fact, have the values [3, 4, 8] and finaldict[4] only having [3], when it should have [2, 3, 8].
Not the most beautiful code I've ever written, but here it goes.
I create sets with all the numbers that are related to each other, then create a dictionary of each of those numbers as key, with the other ones as values.
d = {1: [5,6], 3: [4], 8: [2,3]}
pools = []
for key,values in d.items():
for pool in pools:
if key in pool or any(val in pool for val in values):
pool.add(key)
[pool.add(val) for val in values]
break
else:
pools.append(set((key, *values)))
#pools = [{1, 5, 6}, {8, 2, 3, 4}]
finaldict = {k:set.difference(v, set((k,))) for pool in pools for k, v in zip(pool, [pool]*len(pool))}
print(finaldict)
You can use recursion:
d = {1: [5,6], 3: [4], 8: [2,3]}
def groups(v, seen = [], c = []):
if (k:=[i for a, b in d.items() for i in ({a, *b} if v in {a, *b} else []) if i not in {*seen, v}]):
for i in k:
yield from groups(i, seen=seen+[v], c = c+([v] if seen else []))
else:
yield c+[v]
r = {i:[*{j for k in groups(i) for j in k}] for a, b in d.items() for i in [a, *b]}
Output:
{1: [5, 6], 5: [1, 6], 6: [1, 5], 3: [8, 2, 4], 4: [8, 2, 3], 8: [2, 3, 4], 2: [8, 3, 4]}
You can build up the resulting dictionary by merging related groups and assigning the same merged group to every key that is part of it:
d = {1: [5,6], 3: [4], 8: [2,3]}
related = dict()
for key,group in d.items(): # merge/assign groups to keys
merged = set(group).union({key},*(related.get(k,[]) for k in group))
related.update((k,merged) for k in merged)
related = {k:list(g-{k}) for k,g in related.items()} # exclude key from group
print(related)
{1: [5, 6], 5: [1, 6], 6: [1, 5], 3: [8, 2, 4], 4: [8, 2, 3],
2: [8, 3, 4], 8: [2, 3, 4]}
Given:
a_dict = {3: [3, 7], 7: [6, 2], 2: [2, 1], 8: [-3, 9]}
I'm stuck on a problem where I have to return an updated dictionary that contains the sum of the elements inside the list values alongside its key.
For example, the first key pair:
3: [3, 7]
is to be turned into this:
3: 10
Returned updated dictionary should look like this:
{3: 10, 7: 8, 2: 3, 8: 6}
I'm not sure if I should use the values method to isolate the values to get the sum of numbers from the list values.
for key, val in a_dict.items():
a_dict[key] = sum(val)
Use a dict comprehension:
{k: sum(v) for k, v in a_dict.items()}
# {3: 10, 7: 8, 2: 3, 8: 6}
So I am trying to find a way to "merge" a dependency list which is in the form of a dictionary in python, and I haven't been able to come up with a solution. So imagine a graph along the lines of this: (all of the lines are downward pointing arrows in this directed graph)
1 2 4
\ / / \
3 5 8
\ / \ \
6 7 9
this graph would produce a dependency dictionary that looks like this:
{3:[1,2], 5:[4], 6:[3,5], 7:[5], 8:[4], 9:[8], 1:[], 2:[], 4:[]}
such that keys are nodes in the graph, and their values are the nodes they are dependent on.
I am trying to convert this into a total ancestry list in terms of a tree, so that each node is a key, and its value is a list of ALL nodes that lead to it, not just it's immediate parents. The resulting dictionary would be:
{3:[1,2], 5:[4], 6:[3, 5, 1, 2, 4], 7:[5, 4], 8:[4], 9:[8, 4], 1:[], 2:[], 3:[]}
Any suggestions on how to solve this? I have been banging my head into it for a while, tried a recursive solution that I haven't been able to get working.
You can use a chained dict comprehension with list comprehension for up to two nodes.
>>> {k: v + [item for i in v for item in d.get(i, [])] for k,v in d.items()}
{3: [1, 2],
5: [4],
6: [3, 5, 1, 2, 4],
7: [5, 4],
8: [4],
9: [8, 4],
1: [],
2: [],
4: []}
For unlimited depth, you can use a recursive approach
def get_ant(node, d):
if node:
return d.get(node,[]) + [item for x in d.get(node, []) for item in get_ant(x, d) ]
return []
Then,
>>> get_ant(6, d)
[3, 5, 1, 2, 10, 4]
To get all cases:
>>> {k: get_ant(k, d) for k in d.keys()}
{3: [1, 2, 10],
5: [4],
6: [3, 5, 1, 2, 10, 4],
7: [5, 4],
8: [4],
9: [8, 4],
1: [10],
2: [],
4: []}
Here's a really simple way to do it.
In [22]: a
Out[22]: {1: [], 2: [], 3: [1, 2], 4: [], 5: [4], 6: [3, 5], 7: [5], 8: [4], 9: [8]}
In [23]: final = {}
In [24]: for key in a:
...: nodes = set()
...:
...: for val in a[key]:
...: nodes.add(val)
...: if val in a:
...: nodes.update(set(a[val]))
...:
...: final[key] = list(nodes)
In [25]: final
Out[25]:
{1: [],
2: [],
3: [1, 2],
4: [],
5: [4],
6: [3, 1, 2, 5, 4],
7: [5, 4],
8: [4],
9: [8, 4]}
I have a dictionary with lists as values:
my_dict = {1: [2,3], 2: [4, 5], 3: [6, 7]}
and I want to get to update the dictionary to update the values to be the sum of the old list values:
my_dict = {1: 5, 2: 9, 3: 13}
What is the most efficient/pythonic way of doing so? What I usually do is:
for key in my_dict:
my_dict[key] = sum(my_dict[key])
Are there better ways?
You can use a dictionary comprehension:
my_dict = {1: [2,3], 2: [4, 5], 3: [6, 7]}
new_d = {a:sum(b) for a, b in my_dict.items()}
Output:
{1: 5, 2: 9, 3: 13}
You can use reduce instead of sum:
from functools import reduce
my_dict = {1: [2,3], 2: [4, 5], 3: [6, 7]}
final = {k: reduce(lambda x,y: x+y, v) for k,v in my_dict.items()}
output:
{1: 5, 2: 9, 3: 13}
Otherwise you can refer to this thread for more informations.