user1067257
user1067257

Reputation: 453

Alphabetize a List of Multiline Values in Python?

I have a list of names and addresses organized in the following format:

Mr and Mrs Jane Doe  
Candycane Lane  
Magic Meadows, SC 

I have several blocks of data written like this, and I want to be able to alphabetize each block by the last name (Doe, in this case). After doing some digging, the best I can reckon is that I need to make a "List of lists" and then use the last name as a key by which to alphabetize the block. However, given by freshness to python and lack of Google skills, the closest I could find was this. I'm confused as to converting each block to a list and then slicing it; I can't seem to find a way to do this and still be able to alphabetize properly. Any and all guidance is greatly appreciated.

Upvotes: 1

Views: 256

Answers (3)

theodox
theodox

Reputation: 12208

you want to make a new list where each entry is a tuple containing the sort key you want and the whole thing. Sort that list and then get the second component of each entry in the sort:

def get_sort_name (address):
    name, address, city = address.split('\n')
    return (name.split(' ')[-1] , address) # last item of first line & whole thing as tulle


keyed_list = map (get_sort_name, addresses)
keyed_list.sort()
sorted_addresses = [item[1] for item in keyed_list]

Thi could be more compact using lambdas of course but its better to be readable :)

Upvotes: 2

redShadow
redShadow

Reputation: 6777

If I understood correctly, what you want basically is to sort values by "some computation done on the value", in this case the extracted last name.

For that, use the key keyword argument to .sort() or sorted():

def my_key_function(original_name):
    ## do something to extract the last name, for example:
    try:
        return original_name.split(',')[1].strip()
    except IndexError:
        return original_name

my_sorted_values = sorted(my_original_values, key=my_key_function)

The only requirement is that your "key" function is deterministic, i.e. always return the same output for each given input.

You might also want to sort by last name and then first name: in this case, just return a tuple (last, first): if last si the same for two given items, first will be used to further sort the two.

Update

For your specific case, this function should do the trick:

def my_key_function(original_name):
    return original_name.splitlines()[0].split()[-1]

Upvotes: 2

Tim
Tim

Reputation: 12174

Assuming you already have the data in a list

l = ['Mr and Mrs Jane Smith\nCandycane Lane\nMagic Meadows, SC',
     'Mr and Mrs Jane Doe\nCandycane Lane\nMagic Meadows, SC',
     'Mr and Mrs Jane Atkins\nCandycane Lane\nMagic Meadows, SC']

You can specify the key to sort on.

l.sort(key=lambda x: x.split('\n')[0].split(' ')[-1])

In this case, get the last word (.split(' ')[-1]) on the first line (.split('\n')[0])

Upvotes: 2

Related Questions