Python Forum

Full Version: Converting '1a2b3c' string to Dictionary
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hello, I'm currently in school for computer science, graduating next year and I've been browsing some of the leetcode problems. I was a bit disheartened as when I read some of the answers it looks like I'm reading a foreign language. I've been trying to give myself simple problems so I can get comfortable converting different types of data to dictionaries, I still have a few classes to take but have not really worked with them. What I've been trying to do is convert the string '1a2a3c' into a dictionary {1 : a, 2 : b, 3 : c} using a for a loop. Eventually, I want to create a function that does this. So far I've only been able to come up with this

s = '1a2b3c' 
keys = []
keys[:0] = s
dic = {}
for i in keys:
    if (keys.index(i) % 2) == 0:
        dic[keys[i]] = keys[i + 1]
But when I try to run this I get the error

Error:
Traceback (most recent call last): File "<string>", line 7, in <module> TypeError: can only concatenate str (not "int") to str
Does anyone know what I'm doing wrong?
Here is one way
string = '1a2b3c4d'
l1 = []
l2 = []
for char in string:
    l1.append(char) if char.isnumeric() else l2.append(char)
mydict = dict(zip(l1,l2))
print(mydict)
Your problem is you are trying to use a str as a number. You cannot "a" % 2. You can't even "1" % 2. If you want to index the list you need to loop through index values, not list items. You can write your code like this:
keys = list('1a2b3c')
dic = {}
for i in range(len(keys)):
    if (i % 2) == 0:
        dic[keys[i]] = keys[i + 1]
print(dic)
Or better yet:
keys = list('1a2b3c')
dic = {}
for i in range(0, len(keys), 2):
    dic[keys[i]] = keys[i + 1]
print(dic)
Or even better:
keys = list('1a2b3c')
dic = {keys[i]:keys[i+1] for i in range(0, len(keys), 2)}
print(dic)
I would use zip and slices to make (key, value) tuples. The dict() function can use these to make a dictionary
s = "1a2b3c"
sdict = dict(zip(s[::2], s[1::2]))
print(sdict)
s[::2] gets every second character starting at zero ('1', '2', '3').
s[1::2] gets every second character starting at one ('a', 'b', 'c')
zip(s[::2], s[1::2]) generates tuples ('1', 'a'), ('2', 'b'), ('3', 'c')
The dict() function converts the sequence of key, value tuples into a dictionary.
mystring = '1a2b3c4d'
mydict = {mystring[i-1]:mystring[i] for i in range(1, len(mystring), 2)}
from more_itertools import chunked, sliced

spam = '1a2b3c4d'

# without using more_itertools 
print(dict(zip(spam[::2], spam[1::2])))

# using more_itertools
print(dict(chunked(spam, 2)))
print(dict(sliced(spam, 2, strict=True)))
Output:
{'1': 'a', '2': 'b', '3': 'c', '4': 'd'} {'1': 'a', '2': 'b', '3': 'c', '4': 'd'} {'1': 'a', '2': 'b', '3': 'c', '4': 'd'}
Another way could be using built-in zip for clustering a data serie into specified length groups (in this case two) and feed it to built in dict constructor.

From documentation:

Quote:Tips and tricks:

The left-to-right evaluation order of the iterables is guaranteed. This makes possible an idiom for clustering a data series into n-length groups using zip(*[iter(s)]*n, strict=True). This repeats the same iterator n times so that each output tuple has the result of n calls to the iterator. This has the effect of dividing the input into n-length chunks.


>>> s = '1a2b3c4d'
>>> n = 2
>>> dict(zip(*[iter(s)]*n, strict=True))
{'1': 'a', '2': 'b', '3': 'c', '4': 'd'}
Using the same iterator to extract both items for each tuple is brilliant. It is not immediately obvious though. It took a minute for me to understand how it worked,
def todict(kvstring):
    i = iter(kvstring)
    return dict(zip(i, i))