Техника сравнения строк, используемая Python - PullRequest
46 голосов
/ 26 января 2011

Мне интересно, как Python выполняет сравнение строк, а именно, как он определяет результат, когда используется оператор меньше (<) или больше (>).

Например, еслиЯ ставлю print('abc' < 'bac') Я получаю True.Я понимаю, что он сравнивает соответствующие символы в строке, однако неясно, почему существует больше, из-за отсутствия лучшего термина, «вес», помещенный в тот факт, что a меньше, чем b (первая позиция) в первой строке, а нетот факт, что a меньше b во второй строке (вторая позиция).

Ответы [ 8 ]

72 голосов
/ 26 января 2011

Из документов :

При сравнении используется лексикографическое упорядочение: сначала сравниваются первые два элемента, и если они отличаются, это определяет результат сравнения;если они равны, сравниваются следующие два элемента и т. д., пока не будет исчерпана любая последовательность.

Также:

В лексикографическом порядке для строк используется код Unicodeномер точки для упорядочения отдельных символов.

или Python 2 :

В лексикографическом порядке для строк используется порядок символов ASCII для отдельных символов.

Например:

>>> 'abc' > 'bac'
False
>>> ord('a'), ord('b')
(97, 98)

Результат False возвращается, как только a оказывается меньше b.Дальнейшие элементы не сравниваются (как вы можете видеть для вторых элементов: b> a is True).

Помните о нижнем и верхнем регистре:

>>> [(x, ord(x)) for x in abc]
[('a', 97), ('b', 98), ('c', 99), ('d', 100), ('e', 101), ('f', 102), ('g', 103), ('h', 104), ('i', 105), ('j', 106), ('k', 107), ('l', 108), ('m', 109), ('n', 110), ('o', 111), ('p', 112), ('q', 113), ('r', 114), ('s', 115), ('t', 116), ('u', 117), ('v', 118), ('w', 119), ('x', 120), ('y', 121), ('z', 122)]
>>> [(x, ord(x)) for x in abc.upper()]
[('A', 65), ('B', 66), ('C', 67), ('D', 68), ('E', 69), ('F', 70), ('G', 71), ('H', 72), ('I', 73), ('J', 74), ('K', 75), ('L', 76), ('M', 77), ('N', 78), ('O', 79), ('P', 80), ('Q', 81), ('R', 82), ('S', 83), ('T', 84), ('U', 85), ('V', 86), ('W', 87), ('X', 88), ('Y', 89), ('Z', 90)]
8 голосов
/ 26 января 2011

Сравнение строк Python является лексикографическим:

Из документов Python: http://docs.python.org/reference/expressions.html

Строки сравниваются лексикографически с использованием числовых эквивалентов (результат встроенной функции ord ()) своих персонажей.Unicode и 8-битные строки полностью совместимы в этом поведении.

Следовательно, в вашем примере, 'abc' < 'bac', 'a' стоит перед (меньше чем) 'b' численно (в ASCII и Unicodeпредставления), поэтому сравнение заканчивается прямо там.

7 голосов
/ 26 января 2011

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

(1) В зависимости от человеческого языка у вас есть понятие порядка символов: 'a' <'b' <'c' и т. Д. </p>

(2) Первый символ имеет больший вес, чем второй символ: 'az' <'za' (независимо от того, пишется ли язык слева направо или справа налево или бустрофедон) </p>

(3) Если у вас заканчиваются символы для проверки, более короткая строка меньше длинной строки: 'foo' <'food' </p>

Как правило, на компьютерном языке «упорядочение символов» довольно примитивно: каждый символ имеет независимое от языка число ord(character), и символы сравниваются и сортируются с использованием этого числа. Часто такой порядок не соответствует человеческому языку пользователя, и тогда вам нужно заняться «сопоставлением», забавной темой.

3 голосов
/ 19 февраля 2014

Взгляните также на Как сортировать строки юникода в алфавитном порядке в Python? , где речь идет о правилах сортировки, заданных алгоритмом сопоставления Unicode (http://www.unicode.org/reports/tr10/).

Чтобы ответить накомментарий

Что? Как еще можно определить порядок, отличный от слева направо?

от S.Lott, есть знаменитый контр-пример при сортировкеФранцузский язык. Он включает в себя акценты: действительно, можно сказать, что на французском языке буквы сортируются слева направо, а акценты справа налево. Вот контрпример: у нас есть e <é и o <ô,таким образом, вы ожидаете, что слова cote, coté, cote, côté будут отсортированы как cote <coté <côte <côté. Ну, это не то, что происходит, на самом деле у вас есть:удалите "c" и "t", мы получим oe <ée <oé <éé, что в точности соответствует порядку справа налево. </p>

И последнее замечание: вам не следует говорить о слева направо и справа налево сортировка, а точнеео вперед и назад сортировка.

Действительно, есть языки, написанные справа налево, и если вы думаете, что арабский и иврит отсортированы справа налево вы можете быть правы с графической точки зрения, но вы ошибаетесь на логическом уровне!

Действительно, Unicode считает строки символов, закодированные в логическом порядке , и направление записиявление, происходящее на уровне глифов.Другими словами, даже если в слове שלום справа от ламината появляется буква голень, логически это происходит до этого.Чтобы отсортировать это слово, сначала рассмотрим голень, затем ламед, затем вав, затем мем, и это упорядочение forward (хотя на иврите написано справа налево), а французские акцентыотсортировано в обратном направлении (хотя на французском написано слева направо).

3 голосов
/ 26 января 2011

Это лексикографический порядок . Это просто помещает вещи в словарный порядок.

2 голосов
/ 11 сентября 2017

Чистым эквивалентом Python для сравнения строк будет:

def less(string1, string2):
    # Compare character by character
    for idx in range(min(len(string1), len(string2))):
        # Get the "value" of the character
        ordinal1, ordinal2 = ord(string1[idx]), ord(string2[idx])
        # If the "value" is identical check the next characters
        if ordinal1 == ordinal2:
            continue
        # If it's smaller we're finished and can return True
        elif ordinal1 < ordinal2:
            return True
        # If it's bigger we're finished and return False
        else:
            return False
    # We're out of characters and all were equal, so the result depends on the length
    # of the strings.
    return len(string1) < len(string2)

Эта функция делает эквивалент реального метода ( Python 3.6 и Python 2.7 )просто намного медленнее.Также обратите внимание, что реализация не совсем «питонна» и работает только для < сравнений.Это просто чтобы проиллюстрировать, как это работает.Я не проверял, работает ли он как сравнение Питонов для комбинированных символов Юникода .

Более общий вариант будет:

from operator import lt, gt

def compare(string1, string2, less=True):
    op = lt if less else gt
    for char1, char2 in zip(string1, string2):
        ordinal1, ordinal2 = ord(char1), ord(char1)
        if ordinal1 == ordinal2:
            continue
        elif op(ordinal1, ordinal2):
            return True
        else:
            return False
    return op(len(string1), len(string2))
1 голос
/ 26 января 2011

Строки сравниваются лексикографически с использованием числовых эквивалентов (результат встроенной функции ord ()) их символов.В этом случае Unicode и 8-битные строки полностью совместимы.

0 голосов
/ 03 февраля 2016

Вот пример кода, который сравнивает две строки лексикографически.

  a = str(input())
  b = str(input())
  if 1<=len(a)<=100 and 1<=len(b)<=100:
    a = a.lower()
    b = b.lower()
    if a > b:
       print('1')
    elif a < b:
       print( '-1')
    elif a == b:
       print('0') 

для разных входов, выходы -

1- abcdefg
   abcdeff
   1

2- abc
   Abc
   0

3- abs
   AbZ
  -1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...