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

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])

Related

Python: how to converet list of list into a dictionary

I am trying to converet the list of list into a dictionary using defaultdict method.
I have a list of list:
a= [[1,2],[2,3,4], [4,5,6], [3,7], [6,10]]
I want the output in this format:
{1: [0], 2: [0], 2: [1], 3: [1], 4: [1], 4: [2], 5: [2], 6: [2], 3: [3], 7: [3], 6: [4], 10: [4]})
Here is my code:
a =[[1,2],[2,3,4], [4,5,6], [3,7], [6,10]]
clusters = defaultdict(list)
cluster_sz = {}
cliques = []
cluster_idx = 0
for clique in a:
cliques.append(clique)
for v in clique:
clusters[v].append(cluster_idx)
cluster_idx+=1
print(clusters)
The output of this code is:
{1: [0], 2: [0,1], 3: [1,3], 4: [1, 2], 5: [2], 6: [2, 4], 7: [3], 10: [4]})
But I need this type of output:
{1: [0], 2: [0], 2: [1], 3: [1], 4: [1], 4: [2], 5: [2], 6: [2], 3: [3], 7: [3], 6: [4], 10: [4]})
You can try with this approach
So instead of dictionary with overlapping keys, you can create list of dictionaries.
a= [[1,2],[2,3,4], [4,5,6], [3,7], [6,10]]
b = [{r:i} for i,k in enumerate(a) for r in k ]
[{1: 0}, {2: 0}, {2: 1}, {3: 1}, {4: 1}, {4: 2}, {5: 2}, {6: 2}, {3: 3}, {7: 3}, {6: 4}, {10: 4}]
Here is a shortened code with your desired output.
a = [[1,2],[2,3,4], [4,5,6], [3,7], [6,10]]
d = {}
for i, sublist in enumerate(a):
for num in sublist:
if num not in d:
d[num] = []
d[num].append(i)
print(d)
dict = {1: [0], 2: [0,1], 3: [1,3], 4: [1, 2], 5: [2], 6: [2, 4], 7: [3], 10: [4]}
convertedDict = {}
for (i, j) in dict.items():
if len(j) > 1:
for k in j:
convertedDict[i] = [k]
else:
convertedDict[i] = j
print (convertedDict)
{1: [0], 2: [1], 3: [3], 4: [2], 5: [2], 6: [4], 7: [3], 10: [4]}
Those object, have duplicated keys, thats the reason, why, converted dict saving only last value in last iteration.
https://thispointer.com/can-a-dictionary-have-duplicate-keys-in-python/

How to create a dictionary using python list comprehension from 2 list

This is my code:
a=[1,2,3,4,5,6,7]
b=[8,9,10,11,12,13,14]
c=[{i:j} for i in a for j in b]
print(c)
Output is
[{1: 8}, {1: 9}, {1: 10}, {1: 11}, {1: 12}, {1: 13}, {1: 14}, {2: 8}, {2: 9}, {2: 10}, {2: 11}, {2: 12}, {2: 13}, {2: 14}, {3: 8}, {3: 9}, {3: 10}, {3: 11}, {3: 12}, {3: 13}, {3: 14}, {4: 8}, {4: 9}, {4: 10}, {4: 11}, {4: 12}, {4: 13}, {4: 14}, {5: 8}, {5: 9}, {5: 10}, {5: 11}, {5: 12}, {5: 13}, {5: 14}, {6: 8}, {6: 9}, {6: 10}, {6: 11}, {6: 12}, {6: 13}, {6: 14}, {7: 8}, {7: 9}, {7: 10}, {7: 11}, {7: 12}, {7: 13}, {7: 14}]
But I want like:
[{1: 8, 2: 9, 3: 10, 4: 11, 5: 12, 6: 13, 7: 14}]
How to achieve this?
To pair several list together you need to use zip operation zip(a, b),
You may use dict comprehension notation or dict constructor
Wrap in an array if needed
c = dict(zip(a, b)) # {1: 8, 2: 9, 3: 10, 4: 11, 5: 12, 6: 13, 7: 14}
c = [dict(zip(a, b))] # [{1: 8, 2: 9, 3: 10, 4: 11, 5: 12, 6: 13, 7: 14}]
c = {i: j for i, j in zip(a, b)} # {1: 8, 2: 9, 3: 10, 4: 11, 5: 12, 6: 13, 7: 14}
c = [{i: j for i, j in zip(a, b)}] # [{1: 8, 2: 9, 3: 10, 4: 11, 5: 12, 6: 13, 7: 14}]
Your notation [{:} for _ in _] was creating a dict for each iteration, resulting in mulitple dicts in a list [{}, {}, {}]
Use dict with zip
Ex:
a=[1,2,3,4,5,6,7]
b=[8,9,10,11,12,13,14]
print(dict(zip(a, b)))
# --> {1: 8, 2: 9, 3: 10, 4: 11, 5: 12, 6: 13, 7: 14}

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.

How do i create a nested dictionary iteratively?

I want to create a dictionary from a given list, nesting elements as shown below. For instance, given:
lst = range(1, 11)
how do I create a function to create a nested dictionary from this list:
dic = {1: {2: {3: {4: {5: {6: {7: {8: {9: 10}}}}}}}}}
Reverse your list (or better range object). Take the last (now first) element as start value and create a new dict in each iteration through the rest of the reversed list:
>>> r = reversed(range(1, 11))
... d = next(r)
... for x in r:
... d = {x: d}
... d
...
{1: {2: {3: {4: {5: {6: {7: {8: {9: 10}}}}}}}}}
You could use functools.reduce.
import functools
lst = range(1, 11)
functools.reduce(lambda x, y: {y: x}, reversed(lst))
# {1: {2: {3: {4: {5: {6: {7: {8: {9: 10}}}}}}}}}
You can build it from inside out:
result = {9: 10}
for i in range(8, 0, -1):
temp = {i: result}
result = temp
print(result)
# outputs {1: {2: {3: {4: {5: {6: {7: {8: {9: 10}}}}}}}}}
Start from the innermost value, working outward.
At each step, use the previous step's dict as the new val.
def nest_dict(lst):
my_dict = lst[-1]
for val in lst[-2::-1]:
my_dict = {val: my_dict}
return my_dict
print nest_dict(range(1, 11))
Output:
{1: {2: {3: {4: {5: {6: {7: {8: {9: 10}}}}}}}}}

Turn Dictionary of Sets into Dictionary of Lists

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]}

Categories

Resources