2011-01-26 49 views
36

Tôi tự hỏi làm thế nào Python so sánh chuỗi, cụ thể hơn là cách nó xác định kết quả khi sử dụng ký hiệu nhỏ hơn (<) hoặc lớn hơn (>).Kỹ thuật so sánh chuỗi Được sử dụng bởi Python

Ví dụ: nếu tôi đặt in ('abc' < 'bac'), tôi nhận được sự thật. Tôi hiểu rằng nó so sánh các ký tự tương ứng trong chuỗi, tuy nhiên nó không rõ ràng tại sao có nhiều hơn, vì thiếu một thuật ngữ tốt hơn, "trọng lượng" được đặt trên thực tế là một ít hơn b (vị trí đầu tiên) trong chuỗi đầu tiên chứ không phải là thực tế là a nhỏ hơn b trong chuỗi thứ hai (vị trí thứ hai).

+5

gì? Làm cách nào khác có thể đặt hàng được định nghĩa khác ngoài trái sang phải? –

+3

@ S.Lott: từ phải sang trái. Không phải ai cũng làm như vậy, nhưng đó không phải là khả năng duy nhất. – katrielalex

+0

@katrielalex: Nếu bạn cho phép điều đó, bạn phải cho phép ngẫu nhiên và thậm chí chỉ và lẻ và mọi khả năng khác. Sau đó, bạn phải "tham số hóa" toán tử để chọn thứ tự nào. Nếu có được một mặc định, làm thế nào nó có thể khác hơn từ trái sang phải? –

Trả lời

62

Từ docs:

Việc so sánh sử dụng hoặc null đặt hàng: đầu tiên hai mục đầu tiên được so sánh, và nếu chúng khác nhau này xác định kết quả của việc so sánh ; nếu chúng bằng nhau, thì hai mục tiếp theo sẽ được so sánh và do đó, bật, cho đến khi một trong hai chuỗi là cạn kiệt.

Ngoài ra:

hoặc null đặt hàng cho các chuỗi sử dụng số điểm mã Unicode để đặt hàng đặc điểm cá nhân.

hoặc trên Python 2:

đặt hàng hoặc null cho các chuỗi sử dụng thứ tự ASCII cho các ký tự riêng biệt.

Như một ví dụ:

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

Kết quả False được trả về càng sớm càng a được tìm thấy là ít hơn b. Các mục khác không được so sánh (như bạn có thể thấy cho các mục thứ hai: b>aTrue).

Hãy nhận biết của thấp hơn và chữ hoa:

>>> [(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

Chỉ muốn thêm rằng nếu một chuỗi bị cạn kiệt, chuỗi đó ít hơn: ''abc' <'abcd''. – Noumenon

+0

Cảm ơn bạn vì điều này, có thể hữu ích khi thêm rằng nó hoạt động cho chuỗi số. Tôi đã chỉ có vấn đề này '" 24 "> 40' =' True' do 'ord (" 2 ")' = '50' – Procyclinsur

+1

@Procyclinsur nope, đó không phải là những gì thực sự xảy ra. Bạn chỉ có thể so sánh chuỗi và số nguyên trong Python 2 và [logic so sánh khác] (https://stackoverflow.com/q/3270680). '" 24 ">" 40 "' (lưu ý các dấu ngoặc kép) trả về 'Sai'. – vaultah

8

Python chuỗi so sánh là tự từ điển:

Từ Python Documents: http://docs.python.org/reference/expressions.html

Strings được so sánh thứ tự từ điển bằng cách sử dụng tương đương số (kết quả của hàm dựng sẵn() của các ký tự của chúng. Các chuỗi Unicode và 8 bit hoàn toàn tương thích trong hành vi này.

Do đó trong ví dụ của bạn, 'abc' < 'bac', 'a' đến trước (nhỏ hơn) 'b' số (trong biểu diễn ASCII và Unicode), vì vậy so sánh kết thúc ngay tại đó.

+0

Vì vậy, nó có kết thúc sự so sánh ngay sau khi nó phát hiện ra rằng một trong các ký tự nhỏ hơn ký tự tương ứng không? – davelupt

+0

@David: Có. Hoặc nhỏ hơn hoặc lớn hơn. Nếu chúng bằng nhau, các mục tiếp theo sẽ được so sánh. – user225312

3

Đây là lexicographical ordering. Nó chỉ đặt mọi thứ theo thứ tự từ điển.

+0

Điều này thực sự sai, bởi vì một từ điển không tạo sự khác biệt giữa chữ thường và chữ hoa, ví dụ ''a'> 'z'' là' True' trong khi '' a '>' Z''is' False' – seb

1

Strings được so sánh lexicographically bằng cách sử dụng số tương đương (kết quả của hàm dựng sẵn() của ký tự. Các chuỗi Unicode và 8 bit hoàn toàn tương thích trong hành vi này.

6

Python và chỉ là về mọi ngôn ngữ máy tính khác sử dụng cùng một nguyên tắc như (Tôi hy vọng), bạn sẽ sử dụng khi tìm kiếm một từ trong một cuốn từ điển in:

(1) Tùy theo ngôn ngữ của con người có liên quan, bạn có một khái niệm đặt hàng ký tự: 'a' < 'b' < 'c' vv

(2) Ký tự đầu tiên có trọng số lớn hơn ký tự thứ hai: 'az' < 'za' (cho dù ngôn ngữ được viết từ trái sang phải) phải hoặc từ phải sang trái hoặc boustrophedon là hoàn toàn không liên quan)

(3) Nếu bạn hết f ký tự để kiểm tra, chuỗi ngắn hơn ít hơn chuỗi dài hơn: 'foo' < 'thực phẩm'

Thông thường, trong ngôn ngữ máy tính, "khái niệm sắp xếp ký tự" khá nguyên thủy: mỗi ký tự đều có ngôn ngữ con người - số độc lập ord(character) và các ký tự được so sánh và sắp xếp bằng số đó. Thường thì thứ tự đó không phù hợp với ngôn ngữ con người của người dùng, và sau đó bạn cần phải tham gia vào "đối chiếu", một chủ đề thú vị.

3

Hãy xem tại số How do I sort unicode strings alphabetically in Python? nơi thảo luận về các quy tắc sắp xếp được đưa ra bởi Thuật toán thu thập Unicode (http://www.unicode.org/reports/tr10/).

Để trả lời các bình luận

gì? Làm cách nào khác có thể đặt hàng được định nghĩa khác ngoài trái sang phải?

bởi S.Lott, có một ví dụ nổi tiếng khi phân loại tiếng Pháp. Nó liên quan đến dấu trọng âm: thực sự, người ta có thể nói rằng, bằng tiếng Pháp, các chữ cái được sắp xếp từ trái sang phải và dấu trọng từ phải sang trái. Dưới đây là ví dụ phản đối: chúng tôi có e < é và o < ô, vì vậy bạn sẽ mong đợi các từ cote, coté, côte, côté sẽ được sắp xếp dưới dạng cote < coté < côte < côté. Vâng, đây không phải là những gì xảy ra, trên thực tế bạn có: cote < côte < coté < côté, tức là, nếu chúng ta loại bỏ "c" và "t", chúng ta có được oe < ôe < oé < ôe -gần đặt hàng.

Và một nhận xét cuối cùng: bạn không nên nói về trái sang phảitừ phải sang trái sắp xếp mà về mongngược phân loại. Thực tế có những ngôn ngữ được viết từ phải sang trái và nếu bạn nghĩ tiếng Ả Rập và tiếng Do Thái là được sắp xếp từ phải sang trái bạn có thể nhìn từ góc nhìn đồ họa, nhưng bạn sai ở cấp độ hợp lý!

Thật vậy, Unicode xem xét các chuỗi ký tự được mã hóa theo thứ tự logic và hướng viết là hiện tượng xảy ra ở cấp độ glyph.Nói cách khác, ngay cả khi trong từ שלום, ký tự chữ xuất hiện ở bên phải của tên được gắn, một cách hợp lý nó xảy ra trước. Để sắp xếp từ này, trước tiên hãy xem xét chữ cái, sau đó là quai, rồi vav, sau đó là mem, và đây là chuyển tiếp đặt hàng (mặc dù tiếng Do Thái được viết từ phải sang trái), trong khi giọng Pháp được sắp xếp ngược (mặc dù tiếng Pháp được viết từ trái sang phải).

0

Đây là mã mẫu so sánh hai chuỗi theo từ điển.

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

cho các đầu vào khác nhau các đầu ra laø-

1- abcdefg 
    abcdeff 
    1 

2- abc 
    Abc 
    0 

3- abs 
    AbZ 
    -1 
2

Một Python tương đương tinh khiết để so sánh chuỗi sẽ là:

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 

Chức năng này không tương đương với phương pháp sản (Python 3.6Python 2.7) chậm hơn rất nhiều. Cũng lưu ý rằng việc triển khai không chính xác là "pythonic" và chỉ hoạt động đối với các so sánh <. Nó chỉ để minh họa cách nó hoạt động. Tôi đã không kiểm tra nếu nó hoạt động như so sánh Pythons cho combined unicode characters.

Một biến thể tổng quát hơn sẽ là:

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 
Các vấn đề liên quan