Python: split this length-structured string the most elegant way - python

Given this string:
fsw="M525x617M525x617S16d48492x577S10000505x544S22a00506x524S21300487x601S37601511x574S34500482x483
I'd like to convert
fsw[8:] (thus "M525x617S16d48492x577S10000505x544S22a00506x524S21300487x601S37601511x574S34500482x483")
in a dictionary containing:
{'S16d48':'492x577', 'S10000':'505x544', 'S22a00':'506x524', 'S21300':'487x601', 'S37601':'511x574', 'S34500':'482x483'}
I managed to get the following with regexp:
>>> import re
>>> re.findall("S[123][0-9a-f]{2}[0-5][0-9a-f]",fsw[8:])
['S16d48', 'S10000', 'S22a00', 'S21300', 'S37601', 'S34500']
>>> re.findall("S[123][0-9a-f]{2}[0-5][0-9a-f].......",fsw[8:])
['S16d48492x577', 'S10000505x544', 'S22a00506x524', 'S21300487x601', 'S37601511x574', 'S34500482x483']
but as far as a dictionary is concerned... I failed to get any further.
Another question: in a Python dictionary it is well the whole
key-value pair (say "S16d48":"492x577") that must be unique right ?
In advance - thanks a lot.
Regards.

It seems you can alter your expression to
(?P<key>S[123][0-9a-f]{2}[0-5][0-9a-f])
(?P<value>\d+x\d+)
And then do a dict comprehension as in
import re
rx = re.compile(r'(?P<key>S[123][0-9a-f]{2}[0-5][0-9a-f])(?P<value>\d+x\d+)')
data = "M525x617M525x617S16d48492x577S10000505x544S22a00506x524S21300487x601S37601511x574S34500482x483"
result = {m["key"]: m["value"] for m in rx.finditer(data)}
This yields
{'S16d48': '492x577', 'S10000': '505x544', 'S22a00': '506x524', 'S21300': '487x601', 'S37601': '511x574', 'S34500': '482x483'}
See a demo for the expression on regex101.com and for the code on ideone.com.

You can convert the lists you already created to a dictionary in the following way:
import re
fsw="M525x617M525x617S16d48492x577S10000505x544S22a00506x524S21300487x601S37601511x574S34500482x483"
str_lst = re.findall("S[123][0-9a-f]{2}[0-5][0-9a-f]",fsw[8:])
full_lst = re.findall("S[123][0-9a-f]{2}[0-5][0-9a-f].......",fsw[8:])
str_dict = {x: y[len(x):] for x in str_lst for y in full_lst if y.startswith(x)}
This gives:
{'S16d48': '492x577',
'S10000': '505x544',
'S22a00': '506x524',
'S21300': '487x601',
'S37601': '511x574',
'S34500': '482x483'}

Not sure if I have understood what you are trying to do, but one way to obtain your dictionary from that string is
d = {}
for piece in fsw[8:].split('S')[1:]:
d["S"+piece[:5]] = piece[5:]
print(d)

Related

how to create a dictionary from a set of properly formatted tuples in python

Is there a simple way to create a dictionary from a list of formatted tuples. e.g. if I do something like:
d={"responseStatus":"SUCCESS","sessionId":"01234","userId":2000004904}
This creates a dictionary called d. However, if I want to create a dictionary from a string which contains the same string, I can't do that
res=<some command that returns {"responseStatus":"SUCCESS","sessionId":"01234","userId":2000004904}>
print res
# returns {"responseStatus":"SUCCESS","sessionId":"01234","userId":2000004904}
d=dict(res)
This throws an error that says:
ValueError: dictionary update sequence element #0 has length 1; 2 is required
I strongly strongly suspect that you have json on your hands.
import json
d = json.loads('{"responseStatus":"SUCCESS","sessionId":"01234","userId":2000004904}')
would give you what you want.
Use dict(zip(tuples))
>>> u = ("foo", "bar")
>>> v = ("blah", "zoop")
>>> d = dict(zip(u, v))
>>> d
{'foo': 'blah', 'bar': 'zoop'}
Note, if you have an odd number of tuples this will not work.
Based on what you gave is, res is
# returns {"responseStatus":"SUCCESS","sessionId":"01234","userId":2000004904}
So the plan is to grab the string starting at the curly brace to the end and use json to decode it:
import json
# Discard the text before the curly brace
res = res[res.index('{'):]
# Turn that text into a dictionary
d = json.loads(res)
All you need to do in your particular case is
d = eval(res)
And please keep security in mind when using eval, especially if you're mixing it with ajax/json.
UPDATE
Since others pointed out you might be getting this data over the web and it isn't just a "how to make this work" question, use this:
import json
json.loads(res)

How can I parse a dictionary string?

I am trying to convert a string to a dictionary with dict function, like this
import json
p = "{'id':'12589456'}"
d = dict(p)
print d['id']
But I get the following error
ValueError: dictionary update sequence element #0 has length 1; 2 is required
Why does it fail? How can I fix this?
What you have is a string, but dict function can only iterate over tuples (key-value pairs) to construct a dictionary. See the examples given in the dict's documentation.
In this particular case, you can use ast.literal_eval to convert the string to the corresponding dict object, like this
>>> p = "{'id':'12589456'}"
>>> from ast import literal_eval
>>> d = literal_eval(p)
>>> d['id']
'12589456'
Since p is a string containing JSON (ish), you have to load it first to get back a Python dictionary. Then you can access items within it:
p = '{"id":"12589456"}'
d = json.loads(p)
print d["id"]
However, note that the value in p is not actually JSON; JSON demands (and the Python json module enforces) that strings are quoted with double-quotes, not single quotes. I've updated it in my example here, but depending on where you got your example from, you might have more to do.

All possible combinations of dictionary values given input string. Python

I'm trying to get all possible strings from the values in a dictionary given a particular key. For example, 'A' could mean either 'aaa','aba', or 'aac' and 'B' could mean either 'bbb','bab', or 'bbc', etc.
I've given an example of the output where it shows most combinations of the possible strings
import itertools
in_ = 'ABC'
D = {'A':['aaa','aba','aac'],'B':['bbb','bab','bbc'],'C':['ccc','cac','ccb']}
#out_ = ['aaabbbccc','ababbbccc','aacbbbccc','aaababccc','aaabbcccc','aaabbbcac','aaabbbccb'...]
I started writing the code but it started to get REALLY messy and I feel that there is a way to use itertools or something more pythonic to achieve this goal
output = []
for char in in_:
out_string = ''
while char:
for v in D[char]:
while v:
for char2 in in_:
out_string
#not pythonic . . .
Well, you've got itertools imported there. Let's use it! We want to take the Cartesian product D['A'] × D['B'] × D['C'], so we'll do precisely that using itertools.product.
import itertools
in_ = 'ABC'
D = {'A':['aaa','aba','aac'],'B':['bbb','bab','bbc'],'C':['ccc','cac','ccb']}
iterables = [D[character] for character in in_]
out_ = [''.join(tup) for tup in itertools.product(*iterables)]
Now, out_ is:
['aaabbbccc', 'aaabbbcac', 'aaabbbccb', 'aaababccc', 'aaababcac', 'aaababccb',
'aaabbcccc', 'aaabbccac', 'aaabbcccb', 'ababbbccc', 'ababbbcac', 'ababbbccb',
'abababccc', 'abababcac', 'abababccb', 'ababbcccc', 'ababbccac', 'ababbcccb',
'aacbbbccc', 'aacbbbcac', 'aacbbbccb', 'aacbabccc', 'aacbabcac', 'aacbabccb',
'aacbbcccc', 'aacbbccac', 'aacbbcccb']
Is that the result you were going for?

How to get a value within a dictionary within a dictionary with just a string?

I'm trying to create a function that takes in a dictionary and a string and outputs a value within the Dictionary depending on the string.
For example, inputs would be:
D = {'assigned':{'id':4,'name':'myname'},'anotherkey':{'id':4,'name':'myname'}}
s = "['assigned']['id']"
Result:
4
This can also be achieved with the following, but the issue is that the function will only take a dictionary and a string
print D['assigned']['id']
>> 4
If you don't want to use eval(), you can of course parse out the fields of the string yourself, using regular expressions for instance:
import re
def lookup(d, s):
mo = re.match(r"\['([a-z]+)'\]\['([a-z]+)'\]", s)
if mo and len(mo.groups()) == 2:
return d[mo.group(1)][mo.group(2)]
return None
You can do simpler parsing too since the input is pretty fixed.
You can use eval, but you have to be sure that the string does contain things you want:
>>> eval("D"+s)
4
eval can do this
>>> D = {'assigned':{'id':4,'name':'myname'},'anotherkey':{'id':4,'name':'myname'}}
>>> s = "['assigned']['id']"
>>> eval("D" +s)
4

Python compiled eval?

my situation is as follows:
I have a large table like object which is accessed with a string key and integer index; i.e. lookup is like this: value = table.get("Key", index) .
I would like to give the user the opportunity to enter an arbitrary algebraic expression involving the string keys. The code code should then iterate over the second index and evaluate the expression repeatedly.
So for user input like this: "KeyA + 2*math.abs(KeyC)" I would like to run python code resembling:
for index in index_list:
answer = table.get("KeyA", index) + 2*math.abs(table.get("Keyc",index))
I guess can parse the expression using one of the Python Parser libraries I found on the internet, but it is not by any means clear to me how actually "run" the parsed code. Any suggestions?
If your end users can enter variables in figure brackets, {..}, you can use str.format to format your string
>>> expression = '{a}*{b}'
>>> values = {'a': 10, 'b': 20, 'c': 30}
>>> expression.format(**values)
'10*20'
Here values dictionary might be filled with table.get for all keys found in expression, for example with a regular expression:
>>> import re
>>> regexp = re.compile('{(.*?)}')
>>> keys = regexp.findall(expression)
>>> keys
['a', 'b']
>>> table_get = lambda *x: np.random.randint(5)
>>> values = {k: table_get(k) for k in keys}
>>> expression.format(**values)
'1*4'
Then you can refer to Safe way to parse user-supplied mathematical formula in Python for safe expression parsing and evaluation.

Categories