Какой самый простой способ отсортировать список строк следующим образом? - PullRequest
2 голосов
/ 17 октября 2011

У меня есть список строк, которые могут представлять целые числа, а также имена.Сравнение строк по умолчанию делает следующее:

sorted(['1','2','3','4','10','102','14','Alice','John','Sally'])
['1', '10', '102', '14', '2', '3', '4', 'Alice', 'John', 'Sally']

Я хотел бы отсортировать список следующим образом:

['1', '2', '3', '4', '10', '14', '102', 'Alice', 'John', 'Sally']

, что означает:

  1. сортировать всестроки, представляющие целое число в числовом виде
  2. сортировка «реальных» строк в алфавитном порядке и добавление этого списка в (1.)

Я пробовал с методом сравнения, но я незнаете, как правильно определить, представляет ли строка целое число без попытки / кроме?

Заранее спасибо

Ответы [ 4 ]

10 голосов
/ 17 октября 2011

Если нет отрицательных чисел:

lyst = ['1','2','3','4','10','102','14','Alice','John','Sally']
print sorted(lyst, key=lambda k: int(k) if k.isdigit() else k)

Вот версия, которая не зависит от деталей CPython и работает с Python 3:

sorted(lyst, key=lambda k: (0, int(k)) if k.isdigit() else (1, k))

Здесь ключ является кортежем. Первый элемент в кортеже - 0 или 1 для числа или текста, что приводит к сортировке чисел перед текстом. Тогда вторым элементом в кортеже является значение, которое приводит к соответствующей сортировке значений в пределах их группы. Изначально я использовал float("+inf") для сортировки текстовых элементов по числам, но этот подход (вдохновленный ответом Тома Зича) проще и быстрее.

Если вы хотите, чтобы сортировка строк не учитывала регистр, просто добавьте .lower():

sorted(lyst, key=lambda k: (0, int(k)) if k.isdigit() else (1, k.lower()))
5 голосов
/ 17 октября 2011

Это должно работать с версиями sort, которые принимают ключевую функцию.

def sortkey(s):
    try:
        n = int(s)
        return (0, n)
    except ValueError:
        return (1, s)
5 голосов
/ 17 октября 2011

Следующее работает как в Python 2, так и в Python 3:

l = ['1','2','3','4','10','102','14','Alice','John','Sally','33']
num, alpha = [], []
[num.append(elem) if elem.isdigit() else alpha.append(elem) for elem in l]
result = sorted(num, key=int) + sorted(alpha)
print(result)

Это позволяет избежать сравнения строк с целыми числами путем разбиения списка.Причина, по которой следует избегать такого сравнения, заключается в том, что он либо не указан полностью (Python 2), либо запрещен (Python 3).

0 голосов
/ 17 октября 2011

Я бы пошел с функцией сравнения:

import types

def cmp_func(val1, val2):
  # is val1 an integer?
  try: 
    val1 = int(val1)
  except ValueError: 
    pass # val1 is no integer
  try: 
    val2 = int(val2)
  except ValueError: 
    pass #val2 is no integer

  if type(val1) == types.IntType and type(val2) == types.IntType:
    return cmp(val1, val2)
  elif type(val1) == types.StringType and type(val2) == types.IntType:
    # firstly strings, afterwards integer values
    return -1
  elif type(val1) == types.IntType and type(val2) == types.StringType:
    # firstly strings, afterwards integer values
    return 1
  else:
    return cmp(val1, val2)


if __name__ == "__main__":
  my_list = ['1', '10', '102', '14', '2', '3', '4', 'Alice', 'John', 'Sally']
  my_list.sort(cmp_func)
  print(my_list)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...