I have the following strings - they are assignment commands:
lnodenum = 134241
d1 = 0.200000
jobname = 'hcalfzp'
Is there a way to convert this string, containing variables and values, to keys and values of a dictionary? It'd be equivalent to executing the below command:
my_dict = dict(lnodenum = 134241, d1 = 0.200000, jobname = 'hcalfzp')
I guess this is one way to do it:
my_str = """lnodenum = 134241
d1 = 0.200000
jobname = 'hcalfzp' """
exec('my_dict = dict(%s)' % ','.join(my_str.split('\n')))
Not sure whether anyone would think of a more concise way?
Note: I am using my own code for scientific computing, so I don't mind having code with safety concerns like malicious input data. But, I do prefer to have code that is shorter and easier to read :)
There's no need for exec. Just use a regular assignment with the dict function.
my_str = """lnodenum = 134241
d1 = 0.200000
jobname = 'hcalfzp' """
my_dict = dict(pair for pair in (line.strip().split(' = ') for line in my_str.splitlines()))
Result:
>>> my_dict
{'d1': '0.200000', 'lnodenum': '134241', 'jobname': "'hcalfzp'"}
Or, if you'd like to parse each object, use ast.literal_eval with a comprehension:
import ast
my_dict = {k:ast.literal_eval(v) for k,v in (line.strip().split(' = ') for line in my_str.splitlines())}
Result:
>>> my_dict
{'d1': 0.2, 'lnodenum': 134241, 'jobname': 'hcalfzp'}
Related
I get a list here:
my_list=["Alex:1990:London",
"Tony:1993:NYC",
"Kate:2001:Beijing",
"Tony:2001:LA",
"Alex:1978:Shanghai"]
How can I get the target dictionary my_target_dict from my_list in the easiest way?
my_target_dict={
"Alex":["Alex:1990:London", "Alex:1978:Shanghai"],
"Tony":["Tony:1993:NYC", "Tony:2001:LA"],
"Kate":["Kate:2001:Beijing"]
}
Use a defaultdict:
>>> from collections import defaultdict
>>> my_list=["Alex:1990:London", "Tony:1993:NYC", "Kate:2001:Beijing", "Tony:2001:LA", "Alex:1978:Shanghai"]
>>> d = defaultdict(list)
>>> for item in my_list:
... name, *_ = item.partition(":")
... d[name].append(item)
...
>>> d
defaultdict(<class 'list'>, {'Alex': ['Alex:1990:London', 'Alex:1978:Shanghai'], 'Tony': ['Tony:1993:NYC', 'Tony:2001:LA'], 'Kate': ['Kate:2001:Beijing']})
>>> d["Alex"]
['Alex:1990:London', 'Alex:1978:Shanghai']
You can use this comprehension to clean the list wrapped single items:
>>> {k:v if len(v) > 1 else v[0] for k,v in d.items()}
{'Alex': ['Alex:1990:London', 'Alex:1978:Shanghai'], 'Tony': ['Tony:1993:NYC', 'Tony:2001:LA'], 'Kate': 'Kate:2001:Beijing'}
In case you intend to work strictly with lists and dictionaries alone, try this:
my_target_dict=dict()
for value in my_list:
key=value.split(':')[0]
if key in my_target_dict:
my_target_dict[key].append(value)
else:
my_target_dict[key]=[value]
print(my_target_dict)
This is my solution for you:
my_list=["Alex:1990:London", "Tony:1993:NYC", "Kate:2001:Beijing", "Tony:2001:LA", "Alex:1978:Shanghai"]
dict = {}
for idx, content in enumerate(my_list):
name = content[:(content.index(':'))]
if name not in dict:
dict[name] = []
dict[name].append(my_list[idx])
First if you don't know about enumerate, it count your index and
take the content in each element of list.
Second, take name of there people by basic python of string. I use name = content[:(content.index(':'))] in order to take string from start to the first symbol ":".
Third, check if the key of dict exist or not. Otherwise, it will delete all your element in list of that key.
Last but not least, append the element you want into your key dict.
Your finally result:
{'Alex': ['Alex:1990:London', 'Alex:1978:Shanghai'], 'Tony': ['Tony:1993:NYC', 'Tony:2001:LA'], 'Kate': ['Kate:2001:Beijing']}
If you are a beginner (as I see) and don't want to use Python's collections module and do the implementation from scratch (it's imp to understand the concept of background work which collection does).
Once you are familiar with this, you can go with collections module and that is beautiful as it has many classes like defaultdict, OrderedDict etc. which can boost the speed of your work.
Here is what I have tried (do not forget to read the commented lines).
I have written a function named get_my_target_dict() which takes my_list and returns my_target_dict. And this is the modular implemenation (that you should prefer).
re is a module to work with regular expressions. Here it is used to match "Alex: 1990 : London" (i.e. spaces around :) kind of strings if any (by mistake).
import re
def get_my_target_dict(my_list):
my_target_dict = {} # dictionary
for string in my_list:
# "Alex:1990:London" => ["Alex", "1990", "London"]
# "Alex : 1990: London" => ["Alex", "1990", "London"]
items = re.split(r"\s*:\s*", string) # `\s*` is to match spaces around `:`
print(items)
# Alex, Tony etc.
key = items[0]
if key in my_target_dict:
my_target_dict[key].append(string)
else:
my_target_dict[key] = [string]
return my_target_dict
if __name__ == "__main__":
my_list=["Alex:1990:London",
"Tony:1993:NYC",
"Kate:2001:Beijing",
"Tony:2001:LA",
"Alex:1978:Shanghai"]
# Call get_my_target_dict(), pass my_list & get my_target_dict
my_target_dict = get_my_target_dict(my_list)
print(my_target_dict)
# {'Alex': ['Alex:1990:London', 'Alex:1978:Shanghai'], 'Tony': ['Tony:1993:NYC', 'Tony:2001:LA'], 'Kate': ['Kate:2001:Beijing']}
# Pretty printing dictionary
import json
print(json.dumps(my_target_dict, indent=4))
# {
# "Alex": [
# "Alex:1990:London",
# "Alex:1978:Shanghai"
# ],
# "Tony": [
# "Tony:1993:NYC",
# "Tony:2001:LA"
# ],
# "Kate": [
# "Kate:2001:Beijing"
# ]
# }
below is my code, any one can help me to optimize the process by using python 3 build-in library function ?
Dict1 = {'ky1':1, 'ky2':2,'ky_3':3}
Dict2 = {'ky1':4, 'ky2':5,'ky_4':6}
Dict3 = {'ky2':7, 'ky3':8,'ky_5':9}
D = [Dict1,Dict2,Dict3]
Keys_list = []
for i in D:
tmp = list(i.keys())
Keys_list.append(tmp)
Output = list(set.intersection(*map(set,Keys_list)))
My Dict1, Dict2, Dict3 is large dictionary
thanks
If you just want the list of all keys in all of the dictionaries, you can use dict.viewkeys() (For Python 2.7) or dict.keys() in Python 3.x , to get the dictionary view object, and then intersect them.
Example for Python 3.x -
>>> Dict1 = {'ky1':1, 'ky2':2,'ky_3':3}
>>> Dict2 = {'ky1':4, 'ky2':5,'ky_4':6}
>>> Dict3 = {'ky2':7, 'ky3':8,'ky_5':9}
>>>
>>> Dict1.keys() & Dict2.keys() & Dict3.keys()
{'ky2'}
>>> list(Dict1.keys() & Dict2.keys() & Dict3.keys())
['ky2']
For Python 2.7 use Dict1.viewkeys() , etc, instead of .keys() .
If you have a list of dictionaries , one way to do this in one line using functools.reduce() function, would be -
>>> ld = [{'ky1':1, 'ky2':2,'ky_3':3},{'ky1':4, 'ky2':5,'ky_4':6},{'ky2':7, 'ky3':8,'ky_5':9}]
>>> res = list(reduce(lambda x, y: x & y.keys() , ld))
>>> res
['ky2']
Similar logic, using for loop -
>>> ld = [{'ky1':1, 'ky2':2,'ky_3':3},{'ky1':4, 'ky2':5,'ky_4':6},{'ky2':7, 'ky3':8,'ky_5':9}]
>>> res = ld.pop()
>>> for d in ld:
... res = res & d.keys()
...
>>> list(res)
['ky2']
If I understood your question properly, you're looking for the intersecting keys amongst all three dictionaries, right?
If that is the case, you only need to iterate over one of them, and the process is simple.
isect = [i for i in Dict1 if all(i in d for d in (Dict1,Dict2,Dict3))]
print(isect)
The list comprehension iterates over one dict, and each item is looked up in all three dicts. If it is present, it will be added to the list. You'll get:
['ky2']
as the output.
I have dictionary with three-level nesting, eg:
d = {
'sp1':{
'a1':{'c1':2,'c2':3},
'a2':{'c3':1,'c4':4}
},
'sp2':{
'a1':{'c1':3,'c2':3},
'a2':{'c3':2,'c4':0}
}
}
All 2nd-level dictionaries contain the same elements, so I want to change it to
d2 = {'a1':{'c1':{'sp1':2,'sp2':3}, 'c2':{'sp1':3,'sp2':3}}}
i.e. essentially switch nesting order. But when I write code like
d2 = {}
d2['a1']['c1']['sp1'] = 2
It just throws KeyError with whatever values happens to be 'a1'. How do I perform such operation?
If you are doing it manually like the snippet you tried, this is how you should be doing it:
>>> d = {
... 'sp1':{
... 'a1':{'c1':2,'c2':3},
... 'a2':{'c3':1,'c4':4}
... },
... 'sp2':{
... 'a1':{'c1':3,'c2':3},
... 'a2':{'c3':2,'c4':0}
... }
... }
>>>
>>> e = {}
>>> e['a1'] = {}
>>> e['a1']['c1'] = {}
>>> e['a1']['c1']['sp1'] = d['sp1']['a1']['c1']
>>> e['a1']['c2'] = {}
>>> e['a1']['c2']['sp1'] = d['sp1']['a1']['c2']
>>> e['a2'] = {}
>>> e['a2']['c1'] = {}
>>> e['a2']['c2'] = {}
>>> e['a1']['c1']['sp2'] = d['sp2']['a1']['c1']
>>> e['a1']['c2']['sp2'] = d['sp2']['a1']['c2']
>>> e
{'a1': {'c2': {'sp1': 3, 'sp2': 3}, 'c1': {'sp1': 2, 'sp2': 3}}}
>>>
But it is unclear as to why you are doing it. As OmnipotentEntity suggested in the comments, may be you need to use a different data structure to store the data.
To do this, you can use defaultdict, which allows you to define a default initialization action on a dict.
In your case, you want a reverse-order recursive defaultdict, with a classmethod
reverse_recursive_make() which unrolls and reverses the key order:
when passed in a key-value pair or None, returns a (toplevel) dict
when passed in a dict, recurses into each of the {k:v} pairs
I'm not going to write the code for that because what you want can be much more easily achieved with SQL, like I commented.
FOOTNOTE: your version with lambdas (comment below) is perfect.
(If you insist on using dicts, and not some other data structure)
something like this should work
d_final = {}
for k in d.keys():
d2 = d[k]
for k2 in d2.keys():
d3 = d2[k2]
for k3 in d3.keys():
d4 = d_final.get(k2,{})
d4[k] = d3[k3]
d_final[k2] = d4
I may have my indexing off a little, but that should be about right.
i am trying to iterate on a list were the variables in the list are dictionary names and then iterate on the keys in these dictionary
my code is like this :
IA = {"V":"CVolt","T":"CTemp"}
CLR = {"V":"CLR_Volt","T":"CLR_Temp"}
GT = {"V":"GT_CVolt","T":"GT_Temp"}
PP = ["IA","GT","CLR"]
AFT = {"IA":0,"GT":0,"CLR":0}
AFV = {"IA":0,"GT":0,"CLR":0}
Voltage=0
Vs ={"IA":0.85,"GT":0.85,"CLR":0.85}
Tempreture = 0
Ts ={"IA":30,"GT":30,"CLR":30}
EAK = 7e3
Stress = {"IA":0,"GT":0,"CLR":0}
C = 1
Seff={"IA":0,"GT":0,"CLR":0}
csv.DictReader
with open(File,"r+") as Fin:
reader = csv.DictReader(Fin, dialect='excel')
for line in reader:
for i in PP:
AFT[i] = math.exp(EAK*((1/Ts[i])-(1/float(line[i["T"]]))))
AFV[i] = math.exp(float(line[i["T"]])-Vs[i])
Stress[i] = AFT[i] * AFV[i]
Seff[i] = Seff[i]+Stress[i]
my problem is how do i get the value of the Key in dictionary i
AFT[i] = math.exp(EAK*((1/Ts[i])-(1/float(line[i["T"]]))))
in this case at the first loop i would like to get line["CTemp"]
any suggestions or different approach is welcome
you can either use python's built in locals() function:
>>> IA = {"V":"CVolt","T":"CTemp"}
>>> locals()['IA']
{'T': 'CTemp', 'V': 'CVolt'}
>>> locals()['IA']['T']
'CTemp'
or better, have your variables in one big dict like that:
>>> vars = {
'IA': {"V":"CVolt","T":"CTemp"},
'CLR': {"V":"CLR_Volt","T":"CLR_Temp"},
...
}
>>> vars['IA']
{'T': 'CTemp', 'V': 'CVolt'}
>>> vars['IA']['T']
'CTemp'
Thanks #damienfrancois to complete the answer with locals:
math.exp(EAK*((1/Ts[i])-(1/float(line[locals()[i]['T']]))))
with vars dict:
math.exp(EAK*((1/Ts[i])-(1/float(line[vars[i]['T']]))))
You can change your code like this
AFT[i] = math.exp(EAK*((1/Ts[i])-(1/float(line[eval(i)["T"]]))))
Note the use of eval to transform the string IA into the object named IA.
The use of locals(), or of a container dict is probably better though; see #Guy's answer.
Supposing I had a list as follows:
mylist = ['a','b','c','d']
Is it possible to create, from this list, the following dict without using recursion/a recursive function?
{
'a': {
'b': {
'c': {
'd': { }
}
}
}
}
For the simple case, simply iterate and build, either from the end or the start:
result = {}
for name in reversed(mylist):
result = {name: result}
or
result = current = {}
for name in mylist:
current[name] = {}
current = current[name]
The first solution can also be expressed as a one-liner using reduce():
reduce(lambda res, name: {name: res}, reversed(mylist), {})
For this simple case at least, yes:
my_list = ['a', 'b', 'c', 'd']
cursor = built_dict = {}
for value in my_list:
cursor[value] = {}
cursor = cursor[value]
Or for fancyness and reduced readability:
dict = reduce(lambda x, y: {y: x}, reversed(myList), {})
It's worth mentioning that every recursion can be converted into iteration, although sometimes that might not be so easy. For the particular example in the question, it is simple enough, it's just a matter of accumulating the expected result in a variable and traversing the input list in the appropriate order. This is what I mean:
def convert(lst):
acc = {}
for e in reversed(lst):
acc = {e: acc}
return acc
Or even shorter, the above algorithm can be expressed as a one-liner (assuming Python 2.x, in Python 3.x reduce was moved to the functools module). Notice how the variable names in the previous solution correspond to the lambda's parameters, and how in both cases the initial value of the accumulator is {}:
def convert(lst):
return reduce(lambda acc, e: {e: acc}, reversed(lst), {})
Either way, the function convert works as expected:
mylist = ['a','b','c','d']
convert(mylist)
=> {'a': {'b': {'c': {'d': {}}}}}
mydict = dict()
currentDict = mydict
for el in mylist:
currentDict[el] = dict()
currentDict = currentDict[el]