2

I am fairly new to Python and not really sure where to start on this, so please forgive the poor directions.

Say I've got a dictionary:

Dict = {'Name': 'Dr. John Smith'}

How would I go about splitting that to create:

Dict = {'Title': 'Dr.'
        'First': 'John'
        'Last': 'Smith'}
sirandy
  • 1,834
  • 5
  • 27
  • 32
Madnhain
  • 29
  • 3

3 Answers3

4

First, make sure you don't shadow built-in class names. Here you're using a capital D, but it's close enough to be confusing.

There are various ways to approach the problem, but each will involve splitting your string value in your input dictionary.

You can extract the only value, split it via str.split, then use dict + zip to link a list of keys with values:

d = {'Name': 'Dr. John Smith'}
L = ['Title', 'First', 'Last']

split = next(iter(d.values())).split()
res = dict(zip(L, split))

print(res)

{'Title': 'Dr.', 'First': 'John', 'Last': 'Smith'}

There are other ways, e.g. via explicitly defining dictionary keys within the {} constructor, or via a dictionary comprehension. The above solution is generic and minimises repeated references.

jpp
  • 159,742
  • 34
  • 281
  • 339
3

Assuming you want to do this for more than one person, you could store each person as a dictionary like Dicts in a list. This function should do the splitting by spaces and also allows for cases where someone doesn't have a title, i.e., just a first and last name.

def split_names(dict_list):
    l = []
    for dict_i in dict_list:
        new_list = list(dict_i.values())[0].split()
        if len(new_list) == 2:
            l.append(
                {'First': new_list[0],
                 'Last': new_list[1]}
            )
        else:
            l.append(
                {'Title': new_list[0],
                 'First': new_list[1],
                 'Last': new_list[2]}
            )

    return l

Then,

Dicts = {'Name': 'Dr. John Smith'}
split_names(Dicts)

[{'Title': 'Dr.', 'First': 'John', 'Last': 'Smith'}]

Or more generally:

Dicts = [{'Name': 'Dr. John Smith'}, {'Name': 'Mr. Mike Jones'}, {'Name': 'John Doe'}]
split_names(Dicts)

[{'Title': 'Dr.', 'First': 'John', 'Last': 'Smith'},
 {'Title': 'Mr.', 'First': 'Mike', 'Last': 'Jones'},
 {'First': 'John', 'Last': 'Doe'}]
chrisaddy
  • 108
  • 9
  • 1
    This or a similar approach is what a meant by saying `But you will run into trouble if you cannot split it to three parts, then you have to go deeper and write your own function which also handles more or less spaces in the text.` in [my answer](https://stackoverflow.com/a/51867234/2648551). Thanks for the addition. I think it's helpful to see one approach to this. – colidyre Aug 16 '18 at 11:48
  • 1
    Yes, I after I posted I saw your answer and thought "good timing." The only thing a function like this won't do is return a single dictionary for the case of a single person, as you can see in my first output. I went with list of dictionaries as a better generalization since this would be the easiest way to store it in say JSON format. I was assuming there would be more than one coming in at a time, but if it was just a single dictionary at a time, this would turn it into it's own list which makes adding it to an arbitrary stored list easier. – chrisaddy Aug 16 '18 at 12:30
2

It's about splitting a string, not a dictionary key itself. The key's value is of the type string. So this can be done with str.split().

title, first, last = Dict['Name'].split()
new_dict = {"Title": title, "First": first, "Last": last}

But you will run into trouble if you cannot split it to three parts, then you have to go deeper and write your own function which also handles more or less spaces in the text (see also update at the end).

But this should serve as a starting point as requested. Also interesting could be str.partition() or using a regex.

Update:

Here is a solution if you have either 3 name parts or 2 or even 1 without getting into trouble if you have names without title or without title and first name:

zip()-like built-in function filling unequal lengths from left with None value

It's not the ultimate solution to all name variants (extra name parts, other permutation etc.) which would be very hard to solve without false positives.

colidyre
  • 4,170
  • 12
  • 37
  • 53