1

I have a problem with sort. Want to sort the list like

['asd_1qwer', 'asd_14qwer', 'asd_26qwer', 'asd_5qwer']

I found out that i need to add zeros to 1 and 5.

['asd_01qwer', 'asd_05qwer', 'asd_14qwer', 'asd_26qwer']

Dont know how to add it to right position because asd is not static.

list = ['asd_14qwer','asd_5qwer','asd_26qwer','asd_1qwer']
list.sort()

for i in list:
    tempo = i.split('_')[-1].split('qwer')[0]

    if len(tempo) == 1:
        i[:4] + '0' + i[4:]

Edit Need to add 0 to 1-9 and qwer list constant over all labels.

Ch3steR
  • 20,090
  • 4
  • 28
  • 58
credenco
  • 255
  • 2
  • 12
  • Do all the things have the same prefix? If not do you want to sort with only numbers or with both numbers and prefix? As in: `abc_1, xyz_2, abc_3` or `abc_1 abc_3 xyz_2`? – h4z3 Feb 07 '20 at 12:19
  • I need the whole name. qwer is not changing. Need to sort a list correctly for PyPDF2. I need to sort with the numbers only. Forgot to tell it. – credenco Feb 07 '20 at 12:21
  • `qwer` is constant in every string. And you need to add `0` if the string contains `1` or `5` right?? – Ch3steR Feb 07 '20 at 12:24
  • @Ch3steR need to add 0 to 1-9. qwer is constant – credenco Feb 07 '20 at 12:25

6 Answers6

7

Actually, if your goal is to sort the list according to the numerical part of the strings, you don't need to zero-pad these numerical part, you just need to provide key function to sort() that extracts the numeric part as an integer:

l = ['asd_14qwer','asd_5qwer','asd_26qwer','asd_1qwer']
l.sort(key=lambda x: int(x.split('_')[-1].rstrip('qwer')))

Please note that this code does not depend on the characters preceding _, only on the fact that the numerical part is between _ and qwer.

Błotosmętek
  • 12,717
  • 19
  • 29
4

You can sort also without adding zeros:

list = ['asd_14qwer','asd_5qwer','asd_26qwer','asd_1qwer']    
list.sort(key=lambda i: int(i[(i.index('_') + 1):-4]))
print(list)

Output:

['asd_1qwer', 'asd_5qwer', 'asd_14qwer', 'asd_26qwer']
Moshe perez
  • 1,626
  • 1
  • 8
  • 17
3

you can use:

my_list.sort(key=lambda x: int(x[4:][:-4]))

or you can use a regular expression:

import re

my_list.sort(key=lambda x: int(re.search(r'\d+', x).group()))
kederrac
  • 16,819
  • 6
  • 32
  • 55
1
for i in range(len(list)):
    if len(list[i])==9:
        list[i] = list[i][:4]+'0'+list[i][4:]

This will add the zeroes at the required places in the list

nsrCodes
  • 625
  • 10
  • 25
1

a 'natural sort' perhaps

import re
def natsort(lst):
    """natural sort"""
    lst = [str(i) for i in lst]
    import re
    convert = lambda text: int(text) if text.isdigit() else text
    a_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)]
    return sorted(lst, key=a_key)


lst = ['asd_1qwer', 'asd_14qwer', 'asd_26qwer', 'asd_5qwer']

natsort(lst)
Out[3]: ['asd_1qwer', 'asd_5qwer', 'asd_14qwer', 'asd_26qwer']
NaN
  • 2,212
  • 2
  • 18
  • 23
0

Please don't shadow build-in names. I renamed list to my_list below. :)

Also, based on your answers in the comments, your approach was mostly correct, but you don't need to add padding 0 if you're sorting with only numbers - you just need to parse that part as a number! No matter the length - 3, 21, or 111, it will sort correctly then.

sort function has a parameter key where you can set what should be used to sort the elements in the list - that's where we need to put our snippet that extracts and parses the number:

my_list = ['asd_14qwer','asd_5qwer','asd_26qwer','asd_1qwer']
my_list.sort(key=lambda word: int(word.split('_')[-1].split('qwer')[0]))

As you can see, the snippet is similar to what you tried - I just wrapped it in the int call. :)

Result:

['asd_1qwer', 'asd_5qwer', 'asd_14qwer', 'asd_26qwer']
h4z3
  • 5,265
  • 1
  • 15
  • 29