2011-01-26 14 views
36

Mi chiedo come Python esegua il confronto delle stringhe, in particolare come determina il risultato quando viene utilizzato un segno minore di (> <) o maggiore di (>).Tecnica di confronto delle stringhe utilizzata da Python

Ad esempio, se inserisco la stampa ('abc' < 'bac'), mi avverto. Capisco che confronta i caratteri corrispondenti nella stringa, tuttavia non è chiaro il motivo per cui c'è di più, per mancanza di un termine migliore, "peso" posto sul fatto che a è minore di b (prima posizione) nella prima stringa piuttosto che il fatto che a sia minore di b nella seconda stringa (seconda posizione).

+5

Cosa? In quale altro modo l'ordinamento può essere definito diverso da sinistra-a-destra? –

+3

@ S.Lott: da destra a sinistra. Non che qualcuno lo farebbe, ma non è l'unica possibilità. – katrielalex

+0

@katrielalex: Se lo permetti, dovresti consentire la possibilità casuale e solo-sola e solo-dispari e ogni altra possibilità. Quindi dovresti "parametrizzare" l'operatore per scegliere quale ordine. Se ci sarà un default, come potrebbe essere diverso da sinistra a destra? –

risposta

62

Dal docs:

Il comparatore utilizza lessicografico ordine: prima i primi due elementi vengono confrontati, e se differiscono questa determina l'esito del confronto ; se sono uguali, vengono confrontati i due articoli successivi, , e quindi , fino a quando la sequenza non è esaurita.

anche:

ordinamento lessicografico per le stringhe usa il numero di punto di codice Unicode per ordinare i singoli caratteri.

o Python 2:

ordinamento lessicografico per le stringhe usa l'ordinamento ASCII per i singoli caratteri.

Ad esempio:

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

Il risultato False viene restituito appena a, risulta essere inferiore a b. Gli altri articoli non vengono confrontati (come puoi vedere per i secondi articoli: b>a è True).

attenzione in situazioni di bassa e maiuscolo:

>>> [(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)] 
+7

Volevo solo aggiungere che se una sequenza è esaurita, quella sequenza è inferiore: ''abc' <'abcd''. – Noumenon

+0

Grazie per questo, potrebbe essere utile aggiungere che funziona anche con le stringhe numeriche. Stavo solo avendo questo problema '" 24 "> 40' =' True' a causa di 'ord (" 2 ")' = '50' – Procyclinsur

+1

@Procyclinsur no, non è quello che succede realmente. È possibile confrontare stringhe e interi solo in Python 2 e [la logica di confronto è diversa] (https://stackoverflow.com/q/3270680). '" 24 ">" 40 "' (nota le virgolette) restituisce 'False'. – vaultah

8

Python confronto tra stringhe è lessicografico:

Da Python Documenti: http://docs.python.org/reference/expressions.html

stringhe vengono confrontate lexicographically utilizzando gli equivalenti numerici (il risultato della funzione built-in ord()) dei loro personaggi. Stringhe Unicode e 8-bit sono pienamente interoperabili in questo comportamento.

Quindi nel tuo esempio, 'abc' < 'bac', 'a' viene prima (meno-che) 'b' numericamente (in ASCII e Unicode) rappresentazioni, in modo che il confronto finisce proprio lì.

+0

Quindi, termina il confronto non appena scopre che uno dei personaggi è inferiore a quello con cui corrisponde? – davelupt

+0

@David: Sì. O meno di o maggiore di. Se sono uguali, gli oggetti successivi vengono confrontati. – user225312

3

Questo è un lexicographical ordering. Mette semplicemente le cose in ordine di dizionario.

+0

Questo è in realtà sbagliato, perché un dizionario non fa differenza tra lettere minuscole e maiuscole, ad esempio ''a'> 'z'' è' True' mentre '' a '>' Z''is' False' – seb

1

Strings vengono confrontati con lexicographically utilizzando gli equivalenti numerici (il risultato della funzione built-in ord()) dei loro caratteri. Stringhe Unicode e 8-bit sono pienamente interoperabili in questo comportamento.

6

Python e quasi ogni altro linguaggio di programmazione utilizzare gli stessi principi (spero) si usa quando trovare una parola in un dizionario stampata:

(1) A seconda del linguaggio umano coinvolto, hai una nozione di carattere ordinazione: 'a' < 'b' < 'c' ecc

(2) Prima personaggio ha più peso di secondo personaggio: 'az' < 'za' (se la lingua è scritto da sinistra a destra o destra-sinistra o boustrophedon è abbastanza irrilevante)

(3) Se si esaurisce o f caratteri da testare, la stringa più breve è inferiore alla stringa più lunga: 'foo' < 'food'

In genere, in un linguaggio informatico la "nozione di ordinamento dei caratteri" è piuttosto primitiva: ogni personaggio ha una lingua umana -indipendente numero ord(character) e i caratteri vengono confrontati e ordinati utilizzando quel numero. Spesso l'ordinamento non è appropriato per il linguaggio umano dell'utente, e quindi è necessario entrare in "raccolta", un argomento divertente.

3

Dai uno sguardo anche a How do I sort unicode strings alphabetically in Python? dove la discussione riguarda le regole di ordinamento fornite dall'Algorith Collation Algorithm (http://www.unicode.org/reports/tr10/).

Per rispondere al commento

Cosa? In quale altro modo l'ordinamento può essere definito diverso da sinistra-a-destra?

di S.Lott, c'è un famoso contro-esempio quando si ordina la lingua francese. Si tratta di accenti: in effetti, si potrebbe dire che, in francese, le lettere sono ordinate da sinistra a destra e gli accenti da destra a sinistra. Ecco il contro-esempio: abbiamo e < é e o < ô, quindi ti aspetteresti che le parole cote, coté, côte, côté da ordinare come cote coté < côte < côté. Beh, questo non è quello che succede, in effetti si ha: cote cote < coté < côté, cioè, se togliamo "c" e "t", otteniamo < o < oe < ôé, che è esattamente giusto-a -le ordini di partenza.

E un ultima osservazione: non si dovrebbe parlare di da sinistra a destra eda destra a sinistra di smistamento, ma piuttosto di avanti e all'indietro ordinamento.

In effetti ci sono lingue scritte da destra a sinistra e se pensate che l'arabo e l'ebraico sono ordinato da destra a sinistra tu abbia ragione da un punto di vista grafico, ma si sono sbagliati sul piano logico!

Infatti, Unicode considera stringhe di caratteri codificate in ordine logico e la direzione di scrittura è un fenomeno che si verifica a livello di glifo.In altre parole, anche se nella parola שלום la lettera shin appare a destra del lamed, logicamente si verifica prima di it. Per ordinare questa parola si considerano prima lo stinco, poi il lamed, poi il vav, poi il mem, e questo è in avanti in ordine (anche se l'ebraico è scritto da destra a sinistra), mentre gli accenti francesi sono ordinati indietro (anche se il francese è scritto da sinistra a destra).

0

Ecco un codice di esempio che confronta due stringhe lessicograficamente.

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') 

per diversi ingressi le uscite sono-

1- abcdefg 
    abcdeff 
    1 

2- abc 
    Abc 
    0 

3- abs 
    AbZ 
    -1 
2

un pitone equivalente puro per i confronti di stringhe sarebbe:

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 is False 
    return False 

Questa funzione esegue l'equivalente del metodo reale (Python 3.6 e Python 2.7) molto più lento. Si noti inoltre che l'implementazione non è esattamente "pythonic" e funziona solo per i confronti <. È solo per illustrare come funziona. Non ho controllato se funziona come il confronto Python per combined unicode characters.

Una variante più generale sarebbe:

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 False 
Problemi correlati