How to make a dictionary from raw data string

Viewed 1642

Essentially I need to create a dictionary from a string of data

Given :

data = "electron1, gamma5, proton43, boson98, ..."

d(data) would result in:

{'electron':1, 'gamma':5, 'proton':43, 'boson':98, ...}

My current code is showing an error message of "base 10..."

def d(n):
        pair = dict()
        for i in range(0,n):
                word = input().split()
                key = word[0]
                value = word[1]
                pair[key]=value
        print(pair)

n = int(input())          
d ={}                     
for i in range(n):        
    text = input().split()
    d[text[0]] = text[1]
print(d)
3 Answers

You can do that with a regular expression and a generator expression like:

Code:

END_NUMS_RE = re.compile(r'^(\D+)(\d+)$')
dict(END_NUMS_RE.match(x.strip()).groups() for x in data.split(','))

Test Code:

import re
END_NUMS_RE = re.compile(r'^(\D+)(\d+)$')
data = "electron1, gamma5, proton43, boson98"
print(dict(END_NUMS_RE.match(x.strip()).groups() for x in data.split(',')))

Results:

{'electron': '1', 'gamma': '5', 'proton': '43', 'boson': '98'}

But! A Regex:

So for those that are concerned about using a regex:

Let's benchmark a regex answer vs the second most voted answer here:

import re
END_NUMS_RE = re.compile(r'^(\D+)(\d+)$')
data = "electron1, gamma5, proton43, boson98"

def method1():
    return dict(END_NUMS_RE.match(x.strip()).groups()
                for x in data.split(','))

def method2():
    l = data.split(',')
    return {
        ''.join(
            [x for x in item if not x.isdigit()]):
            int(''.join([x for x in item if x.isdigit()])) for item in l
    }


from timeit import timeit
print(timeit(method1, number=10000))
print(timeit(method2, number=10000))

Timing Results:

0.05789754982012146
0.10536237238963242

The regex answer is twice as fast.

An approach without re

Data = "electron1, gamma5, proton43, boson98"
l=Data.split(',')
d={''.join([x for x in item if not x.isdigit()]):int(''.join([x for x in item if x.isdigit()])) for item in l}
print(d)

Output

{'electron': 1, ' gamma': 5, ' proton': 43, ' boson': 98}

There are a couple of different ways you could do this. If you know your list all has entries in the form of strings ending in some numbers, and you want to split those into keys and values in the form of <non_numerical_string>: <integer>, then here's one way to build off of what you have without using regular expressions:

def d(original_string):
    data_dict = {}

    for item in original_string.split(', '):
        for t in enumerate(item):
            if t[1].isdigit():
                split_pos = t[0]
                break
        data_dict[item[:split_pos]] = int(item[split_pos:])

    return data_dict

data = "electron1, gamma5, proton43, boson98"
print(d(data))

In your original example, n = int(input()) takes the user input and tries to transform all of it into an integer. Later on, when you use .split() on the string, this breaks it up by spaces, but that means the commas are part of the individual strings of your new list. So passing in "(", ")" gives you the split you want (though this means your original string has to have everything separated by commas and a space!).

The enumerate(item) part takes a string like boson98 and returns an object that can be treated like the list [(0, 'b'), (1, 'o'), (2, 's'), (3, 'o'), (4, 'n'), (5, '3'), (6, '8')]. Though personally I prefer the simplicity of a regexp.

Related