2015-04-18 3 views
0

Когда я пытаюсь это, я не могу получить результат, я после -Сортировка алфавитно-цифровых последовательностей неверна. Как я могу улучшить его?

>>> test = { '3 Silver', '3 Oct', '4AD', '99 Reese', '1991', 'alpha', 'beta' } 
>>> sorted(test) 
['1991', '3 Oct', '3 Silver', '4AD', '99 Reese', 'alpha', 'beta'] 

Это не правильно, потому что 1991 является самой высокой записью, начинающейся с цифрой и должна предстать перед alpha

Есть ли у кого-нибудь какие-либо предложения о том, как я могу сортировать это так, как мне хотелось бы?

+2

Какой результат вы хотите получить? –

+1

Поиск "натурального сорта". –

+1

@JeremyBanks, он хочет, чтобы «1991» переместился прямо перед «альфой». – dbliss

ответ

1

Если вы хотите, чтобы отсортировать элементы, учитывая численное (необходимо учитывать краевые случаи, но следует указывать в правильном направлении):

from itertools import takewhile, dropwhile 

test = ['3 Silver', '3 Oct', '4AD', '99 Reese', '1991', 'alpha', 'beta'] 

items = dict() 
for word in test: 
    ordlist = [] 
    ## prenumber will be zero if there are no numerical characters 
    prenumber = int(''.join(list(takewhile(lambda i: i.isdigit() , word))) or 0) 
    ## setting words that start with alpha characters to have infinity as 
    ## first item. This puts them at the end of the list for sorting. 
    ordlist.append(prenumber or float("inf")) 
    ordlist.extend((ord(ch) for ch in dropwhile(lambda i: i.isdigit(), word))) 
    items[word] = ordlist 

### sort dictionary by value 
s = sorted(zip(items.values(), items.keys())) 
print(s) 
## [([3, 32, 79, 99, 116], '3 Oct'), 
## ([3, 32, 83, 105, 108, 118, 101, 114], '3 Silver'), 
## ([4, 65, 68], '4AD'), 
## ([99, 32, 82, 101, 101, 115, 101], '99 Reese'), 
## ([1991], '1991'), 
## ([inf, 97, 108, 112, 104, 97], 'alpha'), 
## ([inf, 98, 101, 116, 97], 'beta')] 

test_sorted = [e[1] for e in s] 
## ['3 Oct', '3 Silver', '4AD', '99 Reese', '1991', 'alpha', 'beta'] 
+0

Это хорошо работает, спасибо! Но он удаляет повторяющиеся записи, поэтому количество элементов на выходе и на входе не обязательно одинаково. – openCivilisation

0

Да, вы можете сделать это, но вы должны создать свой собственный «скоринг» систему, которая будет создавать порядок, что вы хотите:

import re 

def score(token): 
    n = re.sub(r'\D+', '', token) 
    if n: 
     n = int(n) 
    w = re.sub(r'[\d+ ]', '', token) 
    return n, w #returning a list/tuple with the most important criteria on the first place, 2nd on the second place, etc 



arr = ['3 Silver', '3 Oct', '4AD', '99 Reese', '1991', 'alpha', 'beta'] 
print sorted(arr, key=score) # ['3 Oct', '3 Silver', '4AD', '99 Reese', '1991', 'alpha', 'beta'] 
+0

Спасибо за предложения, но это не правило вылова, которое вы описали, я вижу, что вы найдете здесь всего 4 цифры. – openCivilisation

+0

@ user1692999 Я только что узнал этот новый трюк: возвращая список/кортеж с самыми важными критериями на первом месте, вторым на втором месте и т. Д. - даст вам именно то, что вы хотели очень элегантным способом, не ограничивая вас определенным ограничения на вход. См. Обновленную функцию 'score()' выше! – alfasin

Смежные вопросы