Custom Unwind Segue не работает как надо

Значение этого сообщения

Я хочу предложить решение без регулярных выражений, которое может применяться в целом. Я создам три функции:

  1. find_first_digit, которые я заимствовал из @AnuragUniyal . Он найдет положение первой цифры или не цифру в строке.
  2. split_digits, которая является генератором, который выделяет строку в цифру и нечетные фрагменты. Он также будет yield целыми числами, когда это цифра.
  3. natural_key просто обертывает split_digits в tuple. Это то, что мы используем в качестве ключа для sorted, max, min.

Функции

def find_first_digit(s, non=False):
    for i, x in enumerate(s):
        if x.isdigit() ^ non:
            return i
    return -1

def split_digits(s, case=False):
    non = True
    while s:
        i = find_first_digit(s, non)
        if i == 0:
            non = not non
        elif i == -1:
            yield int(s) if s.isdigit() else s if case else s.lower()
            s = ''
        else:
            x, s = s[:i], s[i:]
            yield int(x) if x.isdigit() else x if case else x.lower()

def natural_key(s, *args, **kwargs):
    return tuple(split_digits(s, *args, **kwargs))

Мы видим, что это общий в том, что мы можем иметь несколько цифровых фрагментов:

# Note that the key has lower case letters
natural_key('asl;dkfDFKJ:sdlkfjdf809lkasdjfa_543_hh')

('asl;dkfdfkj:sdlkfjdf', 809, 'lkasdjfa_', 543, '_hh')

Или оставить в качестве чувствительного к регистру:

natural_key('asl;dkfDFKJ:sdlkfjdf809lkasdjfa_543_hh', True)

('asl;dkfDFKJ:sdlkfjdf', 809, 'lkasdjfa_', 543, '_hh')

Мы видим, что он сортирует список OP в соответствующем order

sorted(
    ['elm0', 'elm1', 'Elm2', 'elm9', 'elm10', 'Elm11', 'Elm12', 'elm13'],
    key=natural_key
)

['elm0', 'elm1', 'Elm2', 'elm9', 'elm10', 'Elm11', 'Elm12', 'elm13']

Но он может обрабатывать и более сложные списки:

sorted(
    ['f_1', 'e_1', 'a_2', 'g_0', 'd_0_12:2', 'd_0_1_:2'],
    key=natural_key
)

['a_2', 'd_0_1_:2', 'd_0_12:2', 'e_1', 'f_1', 'g_0']

Мой эквивалент регулярного выражения будет

def int_maybe(x):
    return int(x) if str(x).isdigit() else x

def split_digits_re(s, case=False):
    parts = re.findall('\d+|\D+', s)
    if not case:
        return map(int_maybe, (x.lower() for x in parts))
    else:
        return map(int_maybe, parts)

def natural_key_re(s, *args, **kwargs):
    return tuple(split_digits_re(s, *args, **kwargs))
0
задан Gal 16 January 2019 в 16:34
поделиться