Python - using dictionary to count keys and values - python

I am a student in a python course where we created a list of tuples (containing 2 elements) that we're trying to manipulate in various ways. In addition, we are to convert those tuple elements into a dictionary and re-create the manipulations using the dictionary and avoiding for loops. The task I'm stuck on is that given a specific id (which could be a key OR value in the dictionary) the function returns all the other keys/values that are found in that dictionary.
It doesn't seem efficient to use a dictionary for this, but that's the section we are on in the course and is specifically asked by the assignment. Also no for loops (if that is possible?). Recall that the id can be either a key or a value in the dictionary.
example_dictionary = {'A': 'C', 'R': 'E', 'D': 'A', 'L': 'R', 'C': 'D'}
def get_interactions(example_dictionary, id):
output = ''
for j,k in example_dictionary.items():
if j == id:
output = output + k + ' '
if k == id:
output = output + j + ' '
return output
This code works just fine, however it 1) has a for loop (no good) and 2) isn't very pythonic (kind of an eyesore)! How could I use the dictionary more efficiently and condense down my lines? I am in Python 3, Thank you!

Expected result
Having one dictionary and value named wanted, you want to create another dict being copy of
original one with removed all items not having key or value equal to wanted value.
It can be expressed in form of pytest test case with couple of scenarios.
import pytest
scenarios = [
[
# dct
{'A': 'C', 'R': 'E', 'D': 'A', 'L': 'R', 'C': 'D'},
# wanted
"A",
# expected (result)
{'A': 'C', 'D': 'A'},
],
[
# dct
{'A': 'C', 'R': 'E', 'D': 'A', 'L': 'R', 'C': 'D'},
# wanted
"E",
# expected (result)
{'R': 'E'},
],
[
# dct
{'A': 'C', 'R': 'E', 'D': 'A', 'L': 'R', 'C': 'D'},
# wanted
"D",
# expected (result)
{'D': 'A', 'C': 'D'},
],
[
# dct
{'A': 'C', 'R': 'E', 'D': 'A', 'L': 'R', 'C': 'D'},
# wanted
"nothere",
# expected (result)
{},
],
[
# dct
{'A': 'C', 'R': 'E', 'D': 'A', 'L': 'R', 'C': 'D'},
# wanted
"A",
# expected (result)
{'A': 'C', 'D': 'A'},
],
]
# replace with real implementation
def get_key_or_val_itms(dct, wanted):
# something comes here
return result
#pytest.mark.parametrize("scenario", scenarios)
def test_it(scenario):
dct, wanted, expected = scenario
assert get_key_or_val_itms(dct, wanted) == expected
Do not bother with anything apart from scenarios. It lists couple of test scenarios with input
dictionary, value for wanted and expected result.
Building stones for the solution
dict.items() - dict to list of tuples
>>> dct = {'A': 'C', 'R': 'E', 'D': 'A', 'L': 'R', 'C': 'D'}
>>> dct.items()
[('A', 'C'), ('R', 'E'), ('D', 'A'), ('L', 'R'), ('C', 'D')]
testing membership of a value in a tuple/list
>>> 'A' in ('A', 'C')
True
>>> 'A' in ('R', 'E')
False
Lambda function testing, if wanted is present in a tuple
lambda allows "in place" function definition. It is often used in places,
where some functions expects reference to a function.
First, create named function tuple_wanted
>>> wanted = "A"
>>> def tuple_wanted(tpl):
... return wanted in tpl
and test it (note, that wanted has now value "A"):
>>> tuple_wanted(('A', 'C'))
True
>>> tuple_wanted(('R', 'E'))
False
Now create the function. To play with it, we store the result of lambda in fun:
>>> fun = lambda tpl: wanted in tpl
It can be used in the same manner a tuple_wanted before:
>>> fun(('A', 'C'))
True
>>> fun(('R', 'E'))
False
Later on we will use the result of lambda directly (see filter) without
storing it into any variable.
filter removing all list items not passing some test
filter gets test function and iterable (e.g. list of items) to test by it.
Result of calling filter is list of items from the iterable, which passed the test.
In our case, we want to pass only the tuples, containing wanted value (e.g. "A")
>>> filter(tuple_wanted, dct.items())
[('A', 'C'), ('D', 'A')]
>>> filter(fun, dct.items())
[('A', 'C'), ('D', 'A')]
>>> filter(lambda tpl: wanted in tpl, dct.items())
[('A', 'C'), ('D', 'A')]
Convert list of tuples with 2 items into dictionary
>>> tpllst = [('A', 'C'), ('D', 'A')]
>>> dict(tpllst)
{'A': 'C', 'D': 'A'}
Function doing the work
Long version
This version is here to explain what is going on step by step:
def get_key_or_val_itms(dct, wanted):
# dict as [(key, val), (key2, val2), ...]
tpldct = dct.items()
# find tuples, where either key or val equals `wanted` value
# first make function, which detects, the tuple we search for
def tuple_wanted(tpl):
return wanted in tpl
# now use it to filter only what we search for
restpldct = filter(tuple_wanted, tpldct)
# finally, turn the result into dict
return dict(restpldct)
Short version
def get_key_or_val_itms(dct, wanted):
return dict(filter(lambda tpl: wanted in tpl, dct.items()))
Conclusions
It works (with either long or short version of the function):
>>> dct = {'A': 'C', 'R': 'E', 'D': 'A', 'L': 'R', 'C': 'D'}
>>> wanted = "A"
>>> get_key_or_val_itms(dct, wanted)
{'A': 'C', 'D': 'A'}
If you put the function into file with test suite, calling $ py.test -sv the_file.py shall output:
$ py.test -sv the_file.py
py.test================================ test session starts =========================
=======
platform linux2 -- Python 2.7.9, pytest-2.8.7, py-1.4.31, pluggy-0.3.1 -- /home/javl/
.virtualenvs/stack/bin/python2
cachedir: .cache
rootdir: /home/javl/sandbox/stack/dict, inifile:
collected 5 items
countdict.py::test_it[scenario0] PASSED
countdict.py::test_it[scenario1] PASSED
countdict.py::test_it[scenario2] PASSED
countdict.py::test_it[scenario3] PASSED
countdict.py::test_it[scenario4] PASSED
============================= 5 passed in 0.01 seconds ==============================
As can be seen, all the scenarios are passing.
Explanation how py.test works is out of scope of this answer, to learn more about it, see http://pytest.org/latest/

I wouldn't know how to avoid using a for loop, other than making your own for loop, similar to the following:
i = 0
def func(tup, id) {
if i < len(dictionary_items):
output = False
if tup[0] == id or tup[1] == id:
output = id + ' '
i += 1
return output
}
dictionary_items = dictionary.items()
func(dictionary_items[0], id)
func(dictionary_items[1], id)
func(dictionary_items[2], id)
And so on. However, that would be ugly and extremely non-pythonic.
As for making your code more pythonic, you can change the lines output = output + k + ' ' to output += k + ' ' or output = k + ' ' (You're concatenating strings k and ' ' to an empty string, output, which changes nothing about the strings k and ' ').
Furthermore, you could check if j == id or k == id rather than two seperate if statements, then saying output = id + ' ',since if j or k are equal to id, it doesn't matter if you return whichever of j and k is equal to the id or if you return the id itself.

You have to check all the keys and values, so there is always going to be some type of loop. Python has many ways to iterate (ie. loop) through items without explicit use of for.
One good way to iterate through items without for is with the filter, map, and reduce built-in functions along with the lambda syntax for creating small, anonymous functions.
from itertools import chain
# Get values for matching keys and vice versa
values = map(lambda x: x[1] if x[0] == id else None, dct.items())
keys = map(lambda x: x[0] if x[1] == id else None, dct.items())
# Then you filter out the None values
# itertools.chain allows us to conveniently do this in one line
matches = filter(lambda x: x is not None, chain(keys, values))
If you can't use itertools.chain, you'll just need a few extra steps
keys = filter(lambda x: x is not None, keys)
values = filter(lambda x: x is not None, values)
matches = keys + values
If you need a space separated output of values:
output = ' '.join(matches)

You could use list comprehensions, although one could argue that it is a kind of for loop:
example_dictionary = {'A': 'C', 'R': 'E', 'D': 'A', 'L': 'R', 'C': 'D'}
def get_interactions(dic, id):
output =[v for k, v in dic.items() if k == id] + [k for k,v in dic.items() if v == id]
return output

Related

Reverse lookup dict of tuples, or use a different data structure?

I currently have a dictionary of tuples like this:
d = {
0: ('f', 'farm'),
1: ('m', 'mountain'),
2: ('h', 'house'),
3: ('t', 'forest'),
4: ('d', 'desert')
}
It's been working fine until I realized that I need to be able to do a reverse lookup, so given 'f' return 0, or given 'm' return 1
I know that's possible here by creating lists of the keys and values in the dict and cross-referencing them to find the position of the key, but that seems counter productive. I was wondering if there's a different data structure that would be better suited.
All the relationships here are one-to-one. 0 will always map to f, and f will always map to 0
There are already similar questions that you could use as a starting point.
How to implement an efficient bidirectional hash table?
Reverse / invert a dictionary mapping
In your specific case, the dict in its current form may be pointless. Dicts with integer keys starting from zero are just inefficient lists, but lists already have a reverse lookup method called index.
So what you could do is:
places_order = ['f', 'm', 'h', 't', 'd']
and then use places_order.index(some_letter) to get the corresponding integer.
This is an O(n) operation, so I'm assuming you don't need to perform these lookups millions of times with high performance. (Otherwise, especially if the real places_order is a long list, consider dict(zip(places_order, range(len(places_order)))).)
In addition, you could keep a map for the abbreviations of place names.
abbreviations = {
'f': 'farm',
'm': 'mountain',
'h': 'house',
't': 'forest',
'd': 'desert'
}
It's hard to say more without knowing any specifics about what you are trying to achieve.
A most straightforward search would be:
def search(dictionary, word):
for key,value in dictionary.items():
if word in value:
return key
This could then be used as:
>>> search(d, 'h')
2
Not sure I fully understand the use-case, but if you are not looking for a built-in python what about pandas.Series:
import pandas as pd
d = pd.Series(['farm', 'mountain', 'house', 'forest', 'desert'],index = ['f', 'm', 'h', 't', 'd'])
so both d[0] and d['f'] will output 'farm', d.index[0] will give 'f' and d.index.get_loc('f') will give 0.
For the case of built-ins see #timgeb's answer or consider a sort of namedtuple.
Here is another approach:
d = {
0: ('f', 'farm'),
1: ('m', 'mountain'),
2: ('h', 'house'),
3: ('t', 'forest'),
4: ('d', 'desert')
}
for key, value in d.items():
if 'h' in value:
print (key)
break
You can use a dict like this:
abs = {
'f': 'farm',
'm': 'mountain',
'h': 'house',
't': 'forest',
'd': 'desert'
}
when you need to reverse loop:
for i, (key, value) in enumerate(abs.items()):
print(i, key, value) # 0 f farm
when you want items by index:
list(abs.items())[i] # ('f', 'farm')

How to use recursion in heterogenous list and dict

I was learning about recursion in python and solved some common problems like factorial, iterating through nested lists etc.
While solving such problems, I came up with this challenge where you have to use recusion to traverse through a heterogeneous input(an input which contains single str elements, nested lists, dictionary etc).
So the challenge involves traversing through all the values in this input and replace a specified value with another one.
The input used here looks like this:
input = ['a', 'b', {'1':{'o':'a'}}, 'c', 'd', {'T': 'b', 'K': [1, 'a', 3, {'S':{'Z':'t'},'R':{'3':'a'}}, {'key':[66,'a',88]}, ['a', 'c']]}, ['a'], 3, 'r', 'a']
The input is a list which itself contains lists and dicts, and some of these lists and dicts are nested and also have one another in themselves.
And the output that I'm expecting to get is:
# this is the output that should be got at the end, after running the code
['#', 'b', {'1':{'o':'#'}}, 'c', 'd', {'T': 'b', 'K': [1, '#', 3, {'S':{'Z':'t'},'R':{'3':'#'}}, {'key':[66,'#',88]}, ['#', 'c']]}, ['#'], 3, 'r', '#']
# exactly like input but with all 'a' replaced with '#'
# of course we can use treat change the input to string and then use replace() of string module and get the output
# but then this wont be a challenge would it?
correct = ['a', 'b', 'a', 'c', 'd', 'b', 1, 'a', 3, 't', 'a', 66, 'a', 88, 'a', 'c', 'a', 3, 'r', 'a']
The code I wrote is:
remove = 'a'
replace = 'X'
output = []
def recall(input):
for item in input:
if isinstance(item, list):
recall(item)
elif isinstance(item, dict):
for entry in item.values():
recall(entry)
else:
if isinstance(input, dict) and item in input.keys():
if input[item]==remove:
input[item]=replace
output.append(input[item])
else:
output.append(input[item])
else:
if item==remove:
item=replace
output.append(item)
else:
output.append(item)
print(item)
recall(input)
print(output)
This produces the output:
['X', 'b', 'X', 'c', 'd', 'b', 1, 'X', 3, 't', 'X', 66, 'X', 88, 'X', 'c', 'X', 3, 'r', 'X']
# a single list with all the 'a' replaced but there are no dicts with their key value pairs in it
I havn't been able to find a way to achieve the desired output.
Am I doing something wrong? Or is there any way the desired output can be achieved with recursion?
You are appending all the values to a single global output variable regardless of whether they are from a nested dict or list. Instead, you need to get the function to return a value so that the function at the next level up can deal with it appropriately - appending a dict or list in the right position in the nested hierarchy. For example, you could do it this way:
def replace_values(item, replacement):
if isinstance(item, list):
return [replace_values(v, replacement) for v in item]
elif isinstance(item, dict):
return {k: replace_values(v, replacement) for k, v in item.items()}
# Alternatively, in case you need the dict keys to be replaced too:
# return {replacement.get(k, k): replace_values(v, replacement) for k, v in item.items()}
else:
return replacement.get(item, item)
input_list = ['a', 'b', {'1':{'o':'a'}}, 'c', 'd', {'T': 'b', 'K': [1, 'a', 3, {'S':{'Z':'t'},'R':{'3':'a'}}, {'key':[66,'a',88]}, ['a', 'c']]}, ['a'], 3, 'r', 'a']
print(replace_values(input_list, {"a": "#"}))
Note that the type (dict, list, or other) and ordering of the elements are the same in the return value as in the input item. This preserves the nested structure of the input.

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