简体   繁体   中英

How to sort a list of strings by numbers in the string

my question seperates in two parts.

first I need to sort a list like this: a = ['Zone 3', 'Zone', 'Zone 9', 'Zone 10', 'Zone 5'] by the number of the Zone.

The result should look like this: result = ['Zone', 'Zone 3', 'Zone 5', 'Zone 9', 'Zone 10']

I have tried it with the following code:

import numpy as np

a = ['Zone 3', 'Zone', 'Zone 9', 'Zone 10', 'Zone 5']
b = np.empty((0,2))
for i in range(0, len(a)):
    if len(a[i]) > 4: 
        a1 = a[i].split()
        a1 = np.array([[a1[0],int(a1[1])]])
    if len(a[i]) == 4:
        a1 = np.array([[a[i], '']])
        print(a2)
    b = np.append(b, a1, axis=0)
b = b[b[:,1].argsort()]
print(b)

with the result:

[['Zone' '']
 ['Zone' '10']
 ['Zone' '3']
 ['Zone' '5']
 ['Zone' '9']]

The problem seems to be, that argsort() does not recognize the 10 as 10 but as 1.

The second problem accured in the folling code:

seperator = ' '
b = list()
for i in range(len(a)):
    c = seperator.join(b[i])
    print(c)
    b = np.append(b, c)
print(b)

The error Exception has occurred: IndexError list index out of range appears, but the index should be in range.

I hope you can help me with these problems.

I'd make use of Python's in-built sorting functionality. You can use the key parameter to customise how your list is actually sorted.

For example:

a = ['Zone 3', 'Zone', 'Zone 9', 'Zone 10', 'Zone 5']

def zone_key(l):
    try:
        _, v = l.split(' ')
        return int(v)
    except ValueError:
        return 0

print(sorted(a, key=zone_key))

For your second problem: you are trying to access the ith element in the list b ( b[i] ) but you've also defined b to be an empty list ( b = list() ). On the first iteration of your loop i = 0 so it's going to try and access element 0 in list b which does not exist and hence causes the index error.

So it's simple

# Will hold the processed values
my_list = list()

# For every tuple in the list
for tup in a:

    # Split on space
    values = tup.split()

    # See if the length is less than two
    if len(values) < 2:

        # Add a 0 if there is nothing
        my_list.append((values[0], 0))
    else:

        # Otherwise save as it is in a tuple
        my_list.append((values[0], int(values[1])))

# Then simply 
my_list.sort(key= lambda x: x[1])

This will work smoopthly.

as per @hurlenko check natsort :

from natsort import natsorted
natsorted(a, key=lambda y: y.lower())

returns a list of strings:

['Zone', 'Zone 3', 'Zone 5', 'Zone 9', 'Zone 10']

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM