How to go through a string and turn into dictionary

Viewed 74

I have a string that looks like this:

"buyer=Bob&seller=Jan&id_a=234"

I want to convert this to the dictionary:

{"buyer":"Bob", "seller":"Jan", "id_a":234}

HOWEVER, this string can come in any order, so it can also look like this "seller=Jan&buyer=Bob&id_a=234". This of course, should still result in the same dictionary.

How can I do this easily in python? I was using .split() at first, but when I realized that there are multiple possible orderings, I would have to create a super messy solution to accommodate this. Any ideas?

3 Answers

You can use urllib.parse.parse_qs

parse_qs will parse a query string given as a string argument (data of type application/x-www-form-urlencoded) and return data as a dictionary. The dictionary keys are the unique query variable names and the values are lists of values for each name.

>>> import urllib.parse
>>> urllib.parse.parse_qs("buyer=Bob&seller=Jan&id_a=234")
{'buyer': ['Bob'], 'seller': ['Jan'], 'id_a': ['234']}

You can also use urllib.parse.parse_qsl, which will parse a query string given as a string argument (data of type application/x-www-form-urlencoded) and return a list of name, value pairs.

>>> urllib.parse.parse_qsl("buyer=Bob&seller=Jan&id_a=234")
[('buyer', 'Bob'), ('seller', 'Jan'), ('id_a', '234')]

If you wanted to do this using "base" Python, without a query string parsing library, we can try using re.findall:

inp = "buyer=Bob&seller=Jan&id_a=234"
matches = re.findall(r'([^=&]+)=([^=&]+)', inp)
dict_1 = dict()

for key, value in matches: 
    dict_1.setdefault(key, []).append(value) 
print(dict_1)

This prints:

{'buyer': ['Bob'], 'id_a': ['234'], 'seller': ['Jan']}

You have a number of key value pairs, all separated by &. The key and value themselves are separated by =. That sounds like an ideal use case for string.split():

input_string = "buyer=Bob&seller=Jan&id_a=234&other=abc=7"

my_dict = {}
for keyval in input_string.split("&"):
    (key, val) = keyval.split("=", 1)
    my_dict[key] = val

print(my_dict)

The output of that is:

{'buyer': 'Bob', 'seller': 'Jan', 'id_a': '234', 'other': 'abc=7'}

This first splits the entire key/value set into individual key/value items then, for each, extracts the key and value, adding them to you dictionary. There is no problem with re-ordering of the key/value items in the input string because dictionaries are not sequenced.

The only "sneaky" bit is limiting the key/value split so as to ensure only the first = character is the one that splits.

Related