File to dictionary only prints one - python

I have a text file that reads:
a;b
a;c
a;d
b;h
c;e
e;f
e;g
e;j
f;b
g;d
h;b
h;e
i;d
i;e
but when I print it after making it into a dictionary
def read_graph(file_name):
graph = {}
for line in open(file_name):
if ";" in line:
key, val = map(str.strip, line.split(";"))
graph[key] = val
return dict(sorted(graph.items())))
It prints:
{'a': 'b', 'b': 'd', 'c': 'e', 'd': 'g', 'e': 'd', 'f': 'd'}
how do I make it where it prints the keys that repeat?

I assume for this you'd want to use a list of strings instead of a single string as the value, otherwise your dictionary will keep replacing the value for the same key.
Instead of:
{'a': 'b'}
You would probably want a structure such as:
{'a': ['b','c','d']}
Using your function:
def read_graph(file_name):
graph = {}
for line in open(file_name):
if ";" not in line: continue
key, val = line.strip().split(';')
if key not in graph: graph[key] = list()
if val not in graph[key]: graph[key].append(val)
return dict(sorted(graph.items()))
read_graph('file.txt')
{'a': ['b', 'c', 'd'], 'c': ['e'], 'b': ['h'], 'e': ['f', 'g', 'j'], 'g': ['d'], 'f': ['b'], 'i': ['d', 'e'], 'h': ['b', 'e']}

Dictionaries in python (and every other language I know) have unique values for each key, and will overwrite them when you put a new value in for an existing key.
Consider a different kind of data structure, like a set of tuples, e.g.
{('a','b'), ('a','c'), ...}
Or, as it looks like you are making a graph, a dictionary where the values are lists of vertices instead of individual vertices, e.g.
{'a':['b','c'],...}
To make the set of tuples, replace the line
graph[key] = val
with
graph.append((key, val))
To make a dictionary-to-lists, use
if key in graph:
graph[key].append(val)
else:
graph[key] = [val]
Hope this helps!

You cannot because that is a dictionary, and it is not allowed to have two same keys or it would ambiguous. You could group by key.
def read_graph(file_name):
graph = {}
for line in open(file_name):
if ";" in line:
key, val = map(str.strip, line.split(";"))
if key not in graph:
graph[key] = [val]
else:
graph[key].append(val)
return dict(sorted(graph.items())))
So now you have for every key, an array with its values.

Since you seem to be working with a graph structure, I would recommend you look at the NetworkX package for Python. They have pre-built graph data-structures for you to use and many algorithms that can operate on them.
import networkx as nx
graph = nx.Graph()
with open(file_name) as f: # This closes the file automatically when you're done
for line in f:
if ";" in line:
source, dest = map(str.strip, line.split(";"))
graph.add_edge(source, dest)
In case you still want to use vanilla Python only:
Python's dictionaries can only have one value per key. To store multiple values for a single key, you have to store your keys in a list of values.
my_dict = {
'a': ['b', 'c', 'd'],
'b': ['h'],
...
}

Related

How to merge keys of dictionary which have the same value?

I need to combine two dictionaries by their value, resulting in a new key which is the list of keys with the shared value. All I can find online is how to add two values with the same key or how to simply combine two dictionaries, so perhaps I am just searching in the wrong places.
To give an idea:
dic1 = {'A': 'B', 'C': 'D'}
dic2 = {'D': 'B', 'E': 'F'}
Should result in:
dic3 = {['A', 'D']: 'B', 'C': 'D', 'E': 'F'}
I am not sure why you would need such a data structure, you can probably find a better solution to your problem. However, just for the sake of answering your question, here is a possible solution:
dic1 = {'A':'B', 'C':'D'}
dic2 = {'D':'B', 'E':'F'}
key_list = list(dic2.keys())
val_list = list(dic2.values())
r = {}
for k,v in dic1.items():
if v in val_list:
i = val_list.index(v) #get index at value
k2 = key_list[i] #use index to retrive the key at value
r[(k, k2)] = v #make the dict entry
else:
r[k] = v
val_list = list(r.values()) #get all the values already processed
for k,v in dic2.items():
if v not in val_list: #if missing value
r[k] = v #add new entry
print(r)
output:
{('A', 'D'): 'B', 'C': 'D', 'E': 'F'}
You can't assign a list as a key in a python dictionary since the key must be hashable and a list is not an ashable object, so I have used a tuple instead.
I would use a defaultdict of lists and build a reversed dict and in the end reverse it while converting the lists to tuples (because lists are not hashable and can't be used as dict keys):
from collections import defaultdict
dic1 = {'A':'B', 'C':'D'}
dic2 = {'D':'B', 'E':'F'}
temp = defaultdict(list)
for d in (dic1, dic2):
for key, value in d.items():
temp[value].append(key)
print(temp)
res = {}
for key, value in temp.items():
if len(value) == 1:
res[value[0]] = key
else:
res[tuple(value)] = key
print(res)
The printout from this (showing the middle step of temp) is:
defaultdict(<class 'list'>, {'B': ['A', 'D'], 'D': ['C'], 'F': ['E']})
{('A', 'D'): 'B', 'C': 'D', 'E': 'F'}
If you are willing to compromise from 1-element tuples as keys, the second part will become much simpler:
res = {tuple(value): key for key, value in temp.items()}

Python - restructure dictionary of lits in a loop

Hi guys I have a dict id_dict where I have some keys. In this keys there are lists as values (sometimes only one item somtimes 4). (These are names of components)
my dict id_dict is created dynamically and the keys and values will always change.
S = {'G': ['crypto'], 'T': ['update', 'monitor', 'ipforum'], 'F': ['update'], 'M': ['crypto','update']}
R = {}
for key, value_list in S.items():
for value in value_list:
if value not in R:
R[value] = []
R[value].append(key)
print(R)
Output:
{'crypto': ['G', 'M'], 'update': ['T', 'F', 'M'], 'monitor': ['T'], 'ipforum': ['T']}
you are actually trying to assign the components list you're iterating in as a key of the dictionary, this is what will cause the error.
try by simply doing:
component_dict[component] = id
maybe try something like:
new_dic = {}
for k, v in dic.items():
for ele in v:
if ele not in new_dic:
new_dic[ele] = []
new_dic[ele].append(k)
new_dic
Note the append
It seems that u call components Instead of component and that cannot be a dict key, this si what causes the error,
In addition you didnt set it as a list and just assigned the value, you need to assign a list of it doesnt exist, and append to it if it does
So:
If dict_components.get(component):
dict_components[component].append(id)
else:
dict_components[component] = [id]
try this
from collections import defaultdict
d = {'G': ['crypto'], 'T': ['update', 'monitor', 'ipforum'], 'F': ['update'], 'M': ['crypto', 'update']}
d1 = defaultdict(list)
for k, v in d.items():
for x in v:
d1[x].append(k)
print(d1)
output
defaultdict(<class 'list'>, {'crypto': ['G', 'M'], 'update': ['T', 'F', 'M'], 'monitor': ['T'], 'ipforum': ['T']})
The easies way will be to use collections.defaultdict - which will save you from multiple tests
from collections import defaultdict
source = {'G': ['crypto'],
'T': ['update', 'monitor', 'ipforum'],
'F': ['update'],
'M': ['crypto','update']}
components = defaultdict(list)
for key, values_list in source.items():
for value in values_list:
components[value].append(key)
And the result will be
defaultdict(list,
{'crypto': ['G', 'M'],
'update': ['T', 'F', 'M'],
'monitor': ['T'],
'ipforum': ['T']})
As an alternative, you may create regular dict and use setdefault method to create lists
components = {}
for key, values_list in source.items():
for value in values_list:
components.setdefault(value, []).append(key)

How can i define a switch-case with several variables being the same? [duplicate]

In Python, I need a dictionary object which looks like:
{'a': 10, 'b': 20, 'c': 10, 'd': 10, 'e': 20}
I've been able to get this successfully by combining the dict.update() and dict.fromkeys() functions like so:
myDict = {}
myDict.update(dict.fromkeys(['a', 'c', 'd'], 10))
myDict.update(dict.fromkeys(['b', 'e'], 20))
However, because the code is being written for novice users who may need to make add keys/values on occasion, I'd prefer a simple bare-bones (Perl-like) syntax such as:
myDict = {}
myDict['a', 'c', 'd'] = 10
myDict['b', 'e'] = 20
This, however, gives me:
myDict = {('a', 'c', 'd'): 10, ('b', 'e'): 20}
Is there a way I can simplify my first example (using dict.update() and dict.fromkeys()) further, and get the dict object I'm looking for?
Or, alternatively, if I have a dict with tuples as in my second example, is there an easy way for me to do a lookup such as myDict['c'] or myDict.get('c') and get the value 10?
I would say what you have is very simple, you could slightly improve it to be:
my_dict = dict.fromkeys(['a', 'c', 'd'], 10)
my_dict.update(dict.fromkeys(['b', 'e'], 20))
If your keys are tuple you could do:
>>> my_dict = {('a', 'c', 'd'): 10, ('b', 'e'): 20}
>>> next(v for k, v in my_dict.items() if 'c' in k) # use .iteritems() python-2.x
10
This is, of course, will return first encountered value, key for which contains given element.
Similar to #SilentGhost but a more declarative syntax (with Python 3.5+) I prefer:
myDict = {
**dict.fromkeys(['a', 'c', 'd'], 10),
**dict.fromkeys(['b', 'e'], 20)
}
Your first example can be simplified using a loop:
myDict = {}
for key in ['a', 'c', 'd']:
myDict[key] = 10
for key in ['b', 'e']:
myDict[key] = 20
No specialized syntax or trickery, and I can't think of anything which would be easier to understand.
Regarding your second question, there is no simple and efficient way to do the lookup as in your second example. I can only think of iterating over the keys (tuples) and checking whether the key is in any of them, which isn't what you're looking for. Stick to using a straightforward dict with the keys you want.
In general, if you are aiming for code that can be understood by novices, stick to the basics such as if conditions and for/while loops.
Dict union (3.9+)
Now with Python 3.9, you can do this:
myDict = dict.fromkeys(['a', 'c', 'd'], 10) | dict.fromkeys(['b', 'e'], 20)
Although personally, I'm not sure I would use this, since it's hard to read.
Dict comprehension
myDict = {
k: v
for keys, v in [(['a', 'c', 'd'], 10), (['b', 'e'], 20)]
for k in keys
}
This is also hard to read, but I'm mentioning it for the sake of completeness.
reference
You could inherit from dict to implement a sort of "update from keys":
class LazyDict(dict):
def keylist(self, keys, value):
for key in keys:
self[key] = value
>>> d = LazyDict()
>>> d.keylist(('a', 'b', 'c'), 10)
>>> d
{'a': 10, 'c': 10, 'b': 10}
but I prefer loop solution
Method:
def multi_key_dict_get(d, k):
for keys, v in d.items():
if k in keys:
return v
return None
Usage:
my_dict = {
('a', 'b', 'c'): 10,
('p', 'q', 'r'): 50
}
value = multi_key_dict_get(my_dict, 'a')
While #SilentGhost's answer works pretty fine with single length of keys, it won't work correctly for those looking for a "multiple character length of keys" solution, and so I've thought of the below solution [...]
let's say that we have the above dict and keys we are looking for:
my_dict = {
'key1':'KEY_1',
('tk1', 'tk2','tk3'):'TK_1_2_3',
'key2':'KEY_2'
}
my_keys = ['key2','ke', 'tk2','k','key','exception'] # key's I'm looking for
the example & SOLUTION below:
for key in my_keys:
print(next((v for k, v in my_dict.items() if (key == k) or (isinstance(k,tuple) and key in k)),None))
CORRECTLY outputs:
KEY_2
None
TK_1_2_3
None
None
None
While with (a slightly modified solution [so it won't throw StopIteration exception] of) #SilentGhost's answer
for key in my_keys:
print(next((v for k, v in my_dict.items() if key in k),None)) # added ((...),None)
the results are WRONG because [...]2 if not a StopIteration exception:
KEY_2
KEY_1
TK_1_2_3
KEY_1
KEY_1
None
While personally I wouldn't really recommend it from a perspective of speed efficiency (at least not for all use cases), it is indeed a way of solving this issue and so I decided to post it.
class MyDict(dict):
def __setitem__(self,keys,value):
if type(keys)!=tuple:keys=(keys,)
for key in keys:super().__setitem__(key,value)
myDict = MyDict()
myDict['a', 'c', 'd'] = 10
myDict['b', 'e'] = 20
print(myDict) # {'a': 10, 'c': 10, 'd': 10, 'b': 20, 'e': 20}

Retrieving single dictionary element in Python [duplicate]

This question already has answers here:
In what order does python display dictionary keys? [duplicate]
(4 answers)
Closed 8 years ago.
I want to retrieve only the fourth item in the dictionary "e" (below).
I tried using the OrderedDict() method, but it didn't work. Here are my results:
from collections import OrderedDict
e = OrderedDict()
e = {'a': 'A',
'b': 'B',
'c': 'C',
'd': 'D',
'e': 'E'
}
for k, v in e.items():
print k, v
print e.items()[3]
The last line returns: ('e', 'E')
So I turned the keys and values into lists, but here's how the lists appeared when I printed them:
['a', 'c', 'b', 'e', 'd']
['A', 'C', 'B', 'E', 'D']
For me, this explained why it happened, but not how it happened.
So, next I sorted them. That gave me the results I was looking for -- but it seemed unnecessarily complicated:
e = {'a': 'A',
'b': 'B',
'c': 'C',
'd': 'D',
'e': 'E'
}
k, v = sorted(e.keys()), sorted(e.values())
print "{}: {}".format(k[3], v[3])
Result:
d: D
OrderedDict() wasn't necessary.
Is there an easier way to do this? And can someone explain why the elements in the dictionary are ordered like this:
keys: 'a', 'c', 'b', 'e', 'd'
values: 'A', 'C', 'B', 'E', 'D'
... which defies the structure of my original dictionary?
You're not using an ordered dict.
e = OrderedDict()
e = {'a': 'A',
'b': 'B',
'c': 'C',
'd': 'D',
'e': 'E'
}
The first line creates an OrderedDict. The second line throws it away and replaces it with a regular dict, which is unordered. (Python variables don't have types.)
But you can't just do this:
e = OrderedDict({'a': 'A', ...})
...because that's still a regular dict, which is still unordered, and OrderedDict can't magically recreate your original source ordering.
Try this:
e = OrderedDict([('a', 'A'), ('b', 'B'), ...])
Now you should have a dict-like object with the ordering you want.
And can someone explain why the elements in the dictionary are ordered like this ... which defies the structure of my original dictionary?
Because dictionaries are unordered. They're just hash maps, and hash maps have no inherent ordering.
Note that you could also do this, which will preserve the pairing of keys and values (whereas your separate sortings will not):
print sorted(e.items())[3]

Making a dictionary from a list of lists

I have been unable to figure this out, I think the problem might be in the way I am making the list of lists. Can anyone help out? Thanks!
My desired outcome is
codondict = {'A': ['GCT','GCC','GCA','GCG'], 'C': ['TGT','TGC'], &c
but what i get is:
{'A': 'A', 'C': 'C', &c.
Here's my terminal:
A=['GCT','GCC','GCA','GCG']
C=['TGT','TGC']
D=['GAT','GAC']
E=['GAA','GAG']
F=['TTT','TTC']
G=['GGT','GGC','GGA','GGG']
H=['CAT','CAC']
I=['ATT','ATC','ATA']
K=['AAA','AAG']
L=['TTA','TTG','CTT','CTC','CTA','CTG']
M=['ATG']
N=['AAT','AAC']
P=['CCT','CCC','CCA','CCG']
Q=['CAA','CAG']
R=['CGT','CGC','CGA','CGG','AGA','AGG']
S=['TCT','TCC','TCA','TCG','AGT','AGC']
T=['ACT','ACC','ACA','ACG']
V=['GTT','GTC','GTA','GTG']
W=['TGG']
Y=['TAT','TAC']
aminoacids=['A','C','D','E','F','G','H','I','K','L','M','N','P','Q','R','S','T','V','W','Y']
from collections import defaultdict
codondict=defaultdict(list)
for i in aminoacids:
... for j in i:(ALSO TRIED for j in list(i))
... ... codondict[i]=j
...
codondict
defaultdict(, {'A': 'A', 'C': 'C', 'E': 'E', 'D': 'D', 'G': 'G', 'F': 'F', 'I': 'I', 'H': 'H', 'K': 'K', 'M': 'M', 'L': 'L', 'N': 'N', 'Q': 'Q', 'P': 'P', 'S': 'S', 'R': 'R', 'T': 'T', 'W': 'W', 'V': 'V', 'Y': 'Y'})
You can try this:
condondict= dict(A=['GCT','GCC','GCA','GCG'],
C=['TGT','TGC'],
D=['GAT','GAC'],
E=['GAA','GAG'],
F=['TTT','TTC'],
G=['GGT','GGC','GGA','GGG'],
H=['CAT','CAC'],
I=['ATT','ATC','ATA'],
K=['AAA','AAG'],
L=['TTA','TTG','CTT','CTC','CTA','CTG'],
M=['ATG'],
N=['AAT','AAC'],
P=['CCT','CCC','CCA','CCG'],
Q=['CAA','CAG'],
R=['CGT','CGC','CGA','CGG','AGA','AGG'],
S=['TCT','TCC','TCA','TCG','AGT','AGC'],
T=['ACT','ACC','ACA','ACG'],
V=['GTT','GTC','GTA','GTG'],
W=['TGG'],
Y=['TAT','TAC'])
The reason to use defaultdict() is to allow access/creation of dictionary values without causing a KeyError, or by-pass using the form:
if key not in mydict.keys():
mydict[key] = []
mydict[key].append(something)
If your not creating new keys dynamically, you don't really need to use defaultdict().
Also if your keys already represent the aminoacids, you and just iterate over the keys themselves.
for aminoacid, sequence in condondict.iteritems():
# do stuff with with data...
Another way to do what you need is using the locals() function, which returns a dictionary containing the whole set of variables of the local scope, with the variable names as the keys and its contents as values.
for i in aminoacids:
codondict[i] = locals()[i]
So, you could get the A list, for example, using: locals()['A'].
That's kind of verbose, and is confusing the name of a variable 'A' with its value A. Keeping to what you've got:
aminoacids = { 'A': A, 'C': C, 'D': D ... }
should get you the dictionary you ask for:
{ 'A' : ['GCT', 'GCC', 'GCA', 'GCG'], 'C' : ['TGT', 'TGC'], ... }
where the order of keys 'A' and 'C' may not be what you get back because dictionaries are not ordered.
You can use globals() built-in too, and dict comprehension:
codondict = {k:globals()[k] for k in aminoacids}
it's better to rely on locals() instead of globals(), like stummjr's solution, but you can't do so with dict comprehension directly
codondict = dict([(k,locals()[k]) for k in aminoacids])
However you can do this:
loc = locals()
codondict = {k:loc[k] for k in aminoacids}
If you change dinamically your aminoacids list or the aminoacids assignments, it's better to use something lazier, like:
codondict = lambda: {k:globals()[k] for k in aminoacids}
with this last you can always use the updated dictionary, but it's now a callable, so use codondict()[x] instead of codondict[x] to get an actual dict. This way you can store the entire dict like hist = codondict() in case you need to compare different historical versions of codondict. That's small enough to be useful in interactive modes, but not recommended in bigger codes, though.

Categories

Resources