Turn Dictionary of Sets into Dictionary of Lists - python

Given the Dictionary of Sets:
{1: {2}, 2: {1, 3, 5}, 3: {2, 4}, 4: {3, 7}, 5: {2, 6}, 6: {5}, 7: {8, 4}, 8: {7}}
Is there anyway I can easily turn it into a Dictionary of Lists?
Desired Output:
{1: [2], 2: [1, 3, 5], 3: [2, 4], 4: [3, 7], 5: [2, 6], 6: [5], 7: [8, 4], 8: [7]}

result = {key: list(values) for key, values in dictionary.items()}

Use dict comprehension and convert set to list using the list() function
a = {1: {2}, 2: {1, 3, 5}, 3: {2, 4}, 4: {3, 7}, 5: {2, 6}, 6: {5}, 7: {8, 4}, 8: {7}}
{k:list(v) for k,v in a.items()}
Out[274]:
{1: [2],
2: [1, 3, 5],
3: [2, 4],
4: [3, 7],
5: [2, 6],
6: [5],
7: [8, 4],
8: [7]}

Related

Appending the counts of lists to a dictionary

I have a large list, which I separated into small sized lists which have elements of occurrences of 1s and 0s, randomly.
Also, the first two lists are made with different parameters from the last two.
Example:
list_of_lists[0] =[1,0,1,1,1,0,1,1,1,0]
list_of_lists[1] =[0,0,0,0,0,0,0,0,0,0]
list_of_lists[2] =[1,1,1,1,1,1,1,1,1,1]
list_of_lists[3] =[0,0,1,1,1,1,1,1,1,0]
I would like to count the occurrences of 1s and 0s in each list, and append them into a dictionary to plot the occurrences.
My trial is as follows:
counts_each = dict()
for i in range(4): #all 4 lists
for k in list_of_lists[i]: #elements of the lists
counts_each[k] = counts_each.get(k, 0) + 1
print(counts_each)
which calculates the general occurrences of the 1s and 0s for the al lists:
{0: 16, 1: 24}
If I do:
list_counts = []
for i in range(4):
counts_each = dict()
for k in list_of_lists[i]:
counts_each[k] = counts_each.get(k, 0) + 1
list_counts.append(counts_each)
print(list_counts)
It does not accumulate all of the counts:
[{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 10},
{0: 10},
{0: 10},
{0: 10},
{0: 10},
{0: 10},
{0: 10},
{0: 10},
{0: 10},
{0: 10},
{1: 10},
{1: 10},
{1: 10},
{1: 10},
{1: 10},
{1: 10},
{1: 10},
{1: 10},
{1: 10},
{1: 10},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7},
{0: 3, 1: 7}]
I would be glad to have some insights of what I am doing wrong.
Thank you.
You can let the collections module do all the counting work for you.
from collections import Counter
list_of_lists = [[] for _ in range(4)]
list_of_lists[0] =[1,0,1,1,1,0,1,1,1,0]
list_of_lists[1] =[0,0,0,0,0,0,0,0,0,0]
list_of_lists[2] =[1,1,1,1,1,1,1,1,1,1]
list_of_lists[3] =[0,0,1,1,1,1,1,1,1,0]
counters = [Counter(l) for l in list_of_lists]
print(*counters, sep="\n")
OUTPUT
Counter({1: 7, 0: 3})
Counter({0: 10})
Counter({1: 10})
Counter({1: 7, 0: 3})
You could use a Dict Comprehension, given your nested list:
list_of_lists = [[1,0,1,1,1,0,1,1,1,0], [0,0,0,0,0,0,0,0,0,0], [1,1,1,1,1,1,1,1,1,1], [0,0,1,1,1,1,1,1,1,0]]
use it in this way:
{ idx: {0: lst.count(0), 1: lst.count(1)} for idx, lst in enumerate(list_of_lists) }
#=> {0: {0: 3, 1: 7}, 1: {0: 10, 1: 0}, 2: {0: 0, 1: 10}, 3: {0: 3, 1: 7}}
In the above case I used the index as a key, but you could just use a list comprehension to get a list of dictionaries:
[ {0: lst.count(0), 1: lst.count(1)} for lst in list_of_lists ]
#=> [{0: 3, 1: 7}, {0: 10, 1: 0}, {0: 0, 1: 10}, {0: 3, 1: 7}]
Chris Doyle's answer is excellent, but perhaps your goal is to understand the problem with your solution, specifically.
You have not included your expected output. If I am correct that your issue with your current solution is the repetition of the counts, and you want an output like this:
[{1: 7, 0: 3}, {0: 10}, {1: 10}, {0: 3, 1: 7}]
Then the issue appears to be with the indenting of the line list_counts.append(counts_each). You are doing this each time through the k loop (looping through the items in the list) when I think you want to do it only after finishing the count for a given list:
list_counts = []
for i in range(4):
counts_each = dict()
for k in list_of_lists[i]:
counts_each[k] = counts_each.get(k, 0) + 1
list_counts.append(counts_each)
print(list_counts)

Lists of list manipulation

My code is the following:
import itertools
lists = [[0,1], [1,2,8], [3,4], [4,2], [2,5], [5,6,7], [8,9,10,11,12]]
names = [item[0] for item in lists]
for x in lists:
del x[0]
answer = {name:set(L) for name,L in zip(names, lists)}
which gives me:
{0: {1}, 1: {2, 8}, 3: {4}, 4: {2}, 2: {5}, 5: {6, 7}, 8: {9, 10, 11, 12}}
But what I want to have is to add a key of a previous items for each of the entries. What I want is to have
{0:{1},1:{0,2,8},3:{1,4},4:{3,2} (...)}
Futhermore I would like to twist it a little I mean as a key I want to have each number I have on a list e.g. as I have 5:{6,7} i want to have as well 6:{5,7} and 7:{5,6} obviously i should not have any duplicates.
My question is how could i achieve this?
To make myself clearer I want to visualize a the following graph:
I find it unlikely you would want to make a dict of all permutations of each list as you have a duplicate numbers in a couple of them so possibly making a list of all the dicts (of which being the permutations of each list) then you could do this:
from itertools import permutations
lists = [[0,1], [1,2,8], [3,4], [4,2], [2,5], [5,6,7], [8,9,10,11,12]]
answer = [{k:set(v) for k, *v in perms} for perms in map(permutations, lists)]
Output for this being:
[{0: {1}, 1: {0}}, {1: {8, 2}, 2: {8, 1}, 8: {1, 2}}, {3: {4}, 4: {3}}, {4: {2}, 2: {4}}, {2: {5}, 5: {2}}, {5: {6, 7}, 6: {5, 7}, 7: {5, 6}}, {8: {9, 10, 11, 12}, 9: {8, 10, 11, 12}, 10: {8, 9, 11, 12}, 11: {8, 9, 10, 12}, 12: {8, 9, 10, 11}}]
Otherwise if you don’t mind losing some of the values to being overwritten then you could use this comprehension
answer = {k:set(v) for perms in map(permutations, lists) for k, *v in perms}
Output of this being:
{0: {1}, 1: {8, 2}, 2: {5}, 8: {9, 10, 11, 12}, 3: {4}, 4: {2}, 5: {6, 7}, 6: {5, 7}, 7: {5, 6}, 9: {8, 10, 11, 12}, 10: {8, 9, 11, 12}, 11: {8, 9, 10, 12}, 12: {8, 9, 10, 11}}
You could do this with defaultdict from collections:
lists = [[0,1], [1,2,8], [3,4], [4,2], [2,5], [5,6,7], [8,9,10,11,12]]
from collections import defaultdict
edges = [ (V[0],Vn) for V in lists for Vn in V[1:] ]
result = next( d for d in [defaultdict(set)] if [d[a].add(b) or d[b].add(a) for a,b in edges])
print( dict(result))
# {0: {1}, 1: {0, 8, 2}, 2: {1, 4, 5}, 8: {1, 9, 10, 11, 12}, 3: {4}, 4: {2, 3}, 5: {2, 6, 7}, 6: {5}, 7: {5}, 9: {8}, 10: {8}, 11: {8}, 12: {8}}
You can use dict comprehension:
lists = [[0,1], [1,2,8], [3,4], [4,2], [2,5], [5,6,7], [8,9,10,11,12]]
answer = {lists[i][0]: set(([lists[i - 1][0]] if i > 0 else []) + lists[i][1:]) for i in range(len(lists))}
First of all, you don't need to build a names list: destructuring assignment will do the trick.
>>> lists = [[0,1], [1,2,8], [3,4], [4,2], [2,5], [5,6,7], [8,9,10,11,12]]
>>> answer = {name:set(L) for name,*L in lists}
>>> answer
{0: {1}, 1: {8, 2}, 3: {4}, 4: {2}, 2: {5}, 5: {6, 7}, 8: {9, 10, 11, 12}}
Now, you want to add the previous name when you compute the current name:list. You just have to zip the list with itself to get the expected result:
>>> answer = {name2:set([name1]+L2) for (name1,*L1), (name2,*L2) in zip([[lists[0][1]]]+lists, lists)}
>>> answer
{0: {1}, 1: {0, 8, 2}, 3: {1, 4}, 4: {2, 3}, 2: {4, 5}, 5: {2, 6, 7}, 8: {5, 9, 10, 11, 12}}
The trick is to add an element before the first version of the list that will not change the first name:list. If you use [lists[0][1]], the first name1 is part of the first list2 and the set will be unchanged.

i want to create a dictionary of list of dictionaries

i want to create a dictionary of an array of dictionaries from a list of node pairs and their weight.
nets = pd.read_table('data/nodes.txt', header = None)
bb = np.array(nets).tolist()
graph = collections.defaultdict(dict)
for row in bb:
graph[row[0]][row[1]]=row[2]
graph[row[1]][row[0]] = row[2]
print(dict(graph))
which resulted in this dictionary
{0: {1: 2, 2: 3, 3: 6, 7: 8}, 1: {0: 2, 2: 5, 4: 7}, 2: {0: 3, 1: 5, 11: 5, `5: 4}, 3: {0: 6, 11: 4, 6: 2}, 4: {1: 7}, 5: {8: 3, 2: 4}, 6: {9: 3, 3: 2}, 7: {0: 8}, 8: {5: 3}, 9: {10: 6, 6: 3}, 10: {9: 6}, 11: {2: 5, 3: 4}}`
and want a it in this form.
{0: [{1: 2}, {2: 3}, {3: 6}, {7: 8}],
1: [{0: 2}, {2: 5}, {4: 7}],
2: [{0: 3}, {1: 5}, {11: 5}, {5: 4}],
3: [{0: 6}, {11: 4}, {6: 2}],
4: [{1: 7}],
5: [{8: 3}, {2: 4}],
6: [{9: 3}, {3: 2}],
7: [{0: 8}, 8: {5: 3}],
9: [{10: 6}, {6: 3}],
10: [{9: 6}],
11: [{2: 5}, {3: 4}]}
You can do this pretty easily if you really want to, though I'd look carefully at where you're going to use this data structure to see if your existing more logical structure could be made to work instead.
Anyway, here's a quick implementation that should do what you want:
graph = collections.defaultdict(list)
for row in bb:
graph[row[0]].append({row[1]: row[2]})
graph[row[1]].append({row[0]: row[2]})

Python Dictionary: Accessing the previous value using current/present key

I want to be able to use a 'present' key and generate it's previous key's values. Here is an example with a starting point from which I am unable to move further:
#d= {}
d = {
{'Neighbour_values': [{3: [2, 89.5488]}, {3: [4, 23.0558]}, {4: [2, 89.5488]}, {5: [2, 89.5488]}, {5: [3, 122.153]}, {5: [4, 22.9872]}, {6: [2, 89.5488]}, {6: [4, 22.9872]}, {7: [2, 89.5488]}, {7: [4, 22.9872]}, {8: [3, 122.153]}, {8: [4, 22.9872]}]},
{'Neighbour_values': [{3: [4, 23.0558]}, {4: [1, 19.9884]}, {4: [3, 122.153]}, {5: [1, 19.9884]}, {6: [1, 19.9884]}, {6: [3, 122.153]}, {7: [1, 19.9884]}, {8: [1, 19.9884]}, {8: [3, 122.153]}]},
{'Neighbour_values': [{3: [2, 89.5488]}, {3: [4, 23.0558]}, {3: [6, 20.4196]}, {4: [1, 19.9884]}, {4: [2, 89.5488]}, {5: [1, 19.9884]}, {5: [4, 22.9872]}, {6: [2, 89.5488]}, {6: [4, 22.9872]}, {7: [2, 89.5488]}, {7: [4, 22.9872]}, {8: [2, 89.5488]}]},
{'Neighbour_values': [{3: [1, 122.153]}, {3: [3, 71.1785]}, {3: [6, 20.4196]}, {4: [6, 20.4196]}, {5: [1, 19.9884]}, {6: [1, 19.9884]}, {6: [3, 122.153]}, {6: [6, 20.4196]}, {7: [1, 19.9884]}, {7: [6, 19.9002]}, {8: [1, 19.9884]}, {8: [3, 122.153]}]},
{'Neighbour_values': [{3: [4, 23.0558]}, {4: [4, 23.0362]}, {6: [3, 122.153]}, {6: [4, 22.9872]}, {7: [4, 22.9872]}, {8: [3, 122.153]}, {8: [4, 22.9872]}]}
}
#print '\n'
#print(d)
for value in range(3,9):
print '--- value ---'
if value == 4:
print value of 'Neighbour_values' in key 3 i.e 89.5488 and in next line 23.0558 (but do not print 2, 4)
#and continue with the other keys in the dictionary i.e "for 2, 3, 4, and 6"
next if value == 4+2:
continue the above logic by printing value of 'Neighbour_values' in key 5 (again, only the float values and not the integers)
Of course a little bit of Pseudo code is written in the code as I do not know what to do further.
Any help is appreciated. Thanks in advance :)
(Using Ubuntu 14.04 32-Bit VM and Python 2.7)
UPDATE
Edited the dictionary to be more precise as to what I want for in the solution.
Hope this makes the question more clear.
In Python, dictionaries do not have a specific order.
However, you CAN use collections.OrderedDict to preserve the order that keys were inserted.
You can use it like so:
d = {'one': 1, 'two': 2, 'three': 3}
ordered = OrderedDict(d)
and to get the previous key's values, you could do something like this:
def previous_value(dictionary, current_key):
# Get the list of keys from the OrderedDict
keys = list(dictionary.keys())
# Get an index of the current key and offset it by -1
index = keys.index(current_key) - 1
# return the previous key's value
return dictionary[keys[index]]
Testing it:
print('value before "three": {}'.format(previous_value(ordered, 'three')))
# prints - value before "three": 2
print('value before "two": {}'.format(previous_value(ordered, 'two')))
# prints - value before "two": 1
Try
print('\n'.join([str(l[value-1][1]) for e in d for l in e[1]['Neighbour_values'] if value-1 in l]))
output
89.5488
23.0558
23.0558
89.5488
23.0558
20.4196
122.153
71.1785
20.4196
23.0558
89.5488
19.9884
122.153
19.9884
89.5488
20.4196
23.0362
89.5488
122.153
22.9872
19.9884
19.9884
22.9872
19.9884
89.5488
22.9872
19.9884
122.153
89.5488
22.9872
19.9884
122.153
20.4196
122.153
22.9872
89.5488
22.9872
19.9884
89.5488
22.9872
19.9884
19.9002
22.9872
Explanation
print('\n'.join( #Separate each element by \n
[ #Start List comprehension
str(l[value-1][1]) #select item 1 from [2, 89.5488]
for e in d #for each main tuple of (1, {'Neighbour_values':...
for l in e[1]['Neighbour_values'] #iterate over dictionary like {3: [2, 89.5488]}
if value-1 in l #select only if key of value-1 is there
]
))
As your keys in this case are int, am not sure if you need to use OrderedDict. But if you are comfortable with your data structure for whatever reason, I'm just posting this as a way to wade through it to achieve your output.
UPDATED for additional detail in OP
Your latest d is not a proper dictionary as it doesn't have keys, so I changed it to a dictionary with keys. If you want the code to work properly please use the d as initialized below:
d = {
1:{'Neighbour_values': [{3: [2, 89.5488]}, {3: [4, 23.0558]}, {4: [2, 89.5488]}, {5: [2, 89.5488]}, {5: [3, 122.153]}, {5: [4, 22.9872]}, {6: [2, 89.5488]}, {6: [4, 22.9872]}, {7: [2, 89.5488]}, {7: [4, 22.9872]}, {8: [3, 122.153]}, {8: [4, 22.9872]}]},
2:{'Neighbour_values': [{3: [4, 23.0558]}, {4: [1, 19.9884]}, {4: [3, 122.153]}, {5: [1, 19.9884]}, {6: [1, 19.9884]}, {6: [3, 122.153]}, {7: [1, 19.9884]}, {8: [1, 19.9884]}, {8: [3, 122.153]}]},
3:{'Neighbour_values': [{3: [2, 89.5488]}, {3: [4, 23.0558]}, {3: [6, 20.4196]}, {4: [1, 19.9884]}, {4: [2, 89.5488]}, {5: [1, 19.9884]}, {5: [4, 22.9872]}, {6: [2, 89.5488]}, {6: [4, 22.9872]}, {7: [2, 89.5488]}, {7: [4, 22.9872]}, {8: [2, 89.5488]}]},
4:{'Neighbour_values': [{3: [1, 122.153]}, {3: [3, 71.1785]}, {3: [6, 20.4196]}, {4: [6, 20.4196]}, {5: [1, 19.9884]}, {6: [1, 19.9884]}, {6: [3, 122.153]}, {6: [6, 20.4196]}, {7: [1, 19.9884]}, {7: [6, 19.9002]}, {8: [1, 19.9884]}, {8: [3, 122.153]}]},
5:{'Neighbour_values': [{3: [4, 23.0558]}, {4: [4, 23.0362]}, {6: [3, 122.153]}, {6: [4, 22.9872]}, {7: [4, 22.9872]}, {8: [3, 122.153]}, {8: [4, 22.9872]}]}
}
for value in range(3,9):
for in_d in d.values():
for in_in_d in in_d['Neighbour_values']:
if value-1 in in_in_d:
print(in_in_d[value-1][1])

Accessing tuple values in a dict

q = "cats dogs"
d = {'cats': {1: 1, 2: 3, 3: 1, 4: 1}, 'nuts': {3: 1}, 'egg': {5: 1, 6: 2}, 'dogs': {1: 8, 2: 2, 3: 4}, 'idea': {4: 1}, 'frog': {2: 1, 4: 1, 5: 1}}
newList = []
for word in q:
for x,y in d.values():
newList.append(d[word].x())
What I'm attempting to do here is get each first part of the number pairs and put into the list when it corresponds to a word in q. So I'm expecting newList to be [1,2,3,4,1,2,3].
I am getting ValueError: too many values to unpack (expected 2). How should I be doing this?
The values in the dictionary 'd' are actually of type dictionary themselves, not tuples. I think you may want to reorganize this a bit.
for word in q.split(" "):
if word in d:
child_dict = d[word]
for key in child_dict:
newList.append(key)
Is this what you're looking for?
q = "cats dogs"
d = {'cats': {1: 1, 2: 3, 3: 1, 4: 1}, 'nuts': {3: 1}, 'egg': {5: 1, 6: 2}, 'dogs': {1: 8, 2: 2, 3: 4}, 'idea': {4: 1}, 'frog': {2: 1, 4: 1, 5: 1}}
newList = []
for word in q.split(' '):
newList.extend(list(d[word].keys()))
print(newList)
It prints out [1, 2, 3, 4, 1, 2, 3]
q = "cats dogs"
d = {'cats': {1: 1, 2: 3, 3: 1, 4: 1}, 'nuts': {3: 1}, 'egg': {5: 1, 6: 2}, 'dogs': {1: 8, 2: 2, 3: 4}, 'idea': {4: 1}, 'frog': {2: 1, 4: 1, 5: 1}}
newList = []
for word in q.split(' '):
if word in d:
newList.extend([i for i in d[word]])
print(newList)

Categories

Resources