2010-08-18 42 views
8

Tôi đang thực hiện một bộ lọc trong đó tôi kiểm tra xem chuỗi unicode (utf-8 encoding) có chứa các ký tự viết hoa không (trong tất cả các ngôn ngữ). Sẽ ổn với tôi nếu chuỗi ký tự không chứa bất kỳ ký tự có vỏ nào cả.Python: Làm cách nào để kiểm tra xem chuỗi unicode có chứa một ký tự được sắp xếp không?

Ví dụ: 'Hello!' sẽ không vượt qua bộ lọc, nhưng "!" nên vượt qua bộ lọc, vì "!" không phải là một nhân vật có vỏ.

Tôi dự định sử dụng phương thức islower(), nhưng trong ví dụ trên, "!". Islower() sẽ trả về Sai.

Theo tài liệu Python, "Phương thức unicode python islower() trả về True nếu các ký tự được bỏ chuỗi của chuỗi unicode là tất cả chữ thường và chuỗi chứa ít nhất một ký tự được lồng, nếu không, nó sẽ trả về False."

Vì phương thức này cũng trả về Sai khi chuỗi không chứa bất kỳ ký tự có vỏ nào, tức là. "!", Tôi muốn kiểm tra xem chuỗi có chứa bất kỳ ký tự có vỏ nào không.

Something như thế này ....

string = unicode("[email protected]#$%^", 'utf-8') 

#check first if it contains cased characters 
if not contains_cased(string): 
    return True 

return string.islower(): 

Bất kỳ đề xuất cho một chức năng contains_cased()?

Hoặc có thể là cách tiếp cận triển khai khác?

Cảm ơn!

+0

Câu trả lời mà bạn đã chấp nhận có vẻ không chính xác. Xem câu trả lời của tôi. –

Trả lời

6

Here là đầy đủ những tin sốt dẻo về loại ký tự Unicode.

loại văn bao gồm:

Ll -- lowercase 
Lu -- uppercase 
Lt -- titlecase 
Lm -- modifier 
Lo -- other 

Lưu ý rằng Ll <-> islower(); tương tự cho Lu; (Lu or Lt) <-> istitle()

Bạn có thể đọc thảo luận phức tạp về cách viết hoa, bao gồm một số thảo luận về các chữ cái Lm.

Điều trị một cách mù quáng tất cả "chữ cái" như được gắn là sai rõ ràng. Danh mục Lo bao gồm các điểm mã 45301 trong BMP (được tính bằng Python 2.6). Một đoạn lớn trong số này sẽ là các âm tiết của Hangul, các bản đồ CJK, và các nhân vật Đông Á khác - rất khó để hiểu làm thế nào chúng có thể được coi là "bị bỏ rơi".

Bạn có thể muốn xem xét định nghĩa thay thế, dựa trên hành vi (không xác định) của "ký tự được gắn" mà bạn mong đợi. Đây là một nỗ lực đơn giản đầu tiên:

>>> cased = lambda c: c.upper() != c or c.lower() != c 
>>> sum(cased(unichr(i)) for i in xrange(65536)) 
1970 
>>> 

Điều thú vị là có 1216 x Ll và 937 x Lu, tổng cộng 2153 ...phạm vi để điều tra thêm về những gì Ll và Lu thực sự có ý nghĩa.

+0

@ John: Wow. Cảm ơn lời giải thích của bạn. Tôi mất một lúc để hiểu nó. Tôi đã nhìn vào liên kết của bạn, và tôi nghĩ rằng tôi phải nghiên cứu nó rộng rãi hơn. Tôi có cảm giác rằng những gì tôi sẽ tìm ra sẽ giúp tôi sửa chữa rất nhiều mã của mình. Yikes. Cảm ơn! – Albert

+0

@Albert: Đừng hoảng sợ. Như tôi đã gợi ý, trước hết hãy phát triển một định nghĩa về ý nghĩa của bạn bằng "cased". Bạn sẽ áp dụng phương pháp điều trị nào khác cho các ký tự có vỏ như trái ngược với các ký tự không bị xóa? Định nghĩa mẫu của tôi là "char có chữ hoa hoặc chữ thường" đối tác ". Một số (có thể là tất cả) sự khác biệt giữa các ký tự 1970 và 2153 có vẻ là do ký tự được phân loại là 'Ll' vì chúng trông giống như một ký tự chữ thường, nhưng không có đối tác' Lu' và ngược lại - bạn cần phải quyết định xem đây là những "cased" cho các mục đích của bạn. BTW bạn có thể thay đổi câu trả lời được chấp nhận :-) –

+0

@John: Vâng, tôi đang thực sự tạo API cho dịch vụ web của mình. Webservice của tôi chấp nhận một khóa ánh xạ tới một bản ghi cụ thể trong cơ sở dữ liệu của tôi. Khóa có phân biệt chữ hoa chữ thường và khóa có thể được tạo thành từ bất kỳ characteer unicode nào. Vì vậy, để chuẩn hóa tất cả đầu vào, tôi sẽ chuyển đổi tất cả các truy vấn chính thành chữ thường (nếu chúng có chữ hoa tương đương). Một hệ quả của điều đó là khi tôi tạo các khóa bản ghi (mà người dùng của tôi có thể tùy chỉnh), tôi không thể chấp nhận bất kỳ ký tự chữ hoa nào có thể được chuyển đổi thành một chữ thường tương đương với hàm toLower(). Vì vậy, tôi đang cố gắng tạo bộ lọc cho điều đó. Bất kỳ đề xuất? – Albert

7
import unicodedata as ud 

def contains_cased(u): 
    return any(ud.category(c)[0] == 'L' for c in u) 
+0

Arg alex, có điều gì bạn không biết? –

+2

-1 Xử lý các ký tự Đông Á là "được lồng". Xem câu trả lời của tôi. –

+0

+1: giải pháp làm việc (so với lời giải thích tốt đẹp mà không có mã thực thi của John Machin) – oDDsKooL

1

sử dụng mô-đun unicodedata,

unicodedata.category(character) 

lợi nhuận "Ll" cho chữ thường và "Lu" cho những người thân hoa.

here bạn có thể tìm thấy danh sách các loại ký tự unicode

Các vấn đề liên quan