2010-09-02 38 views
102

Tôi thích sử dụng biểu thứcTrường hợp không nhạy cảm 'trong' - Python

if 'MICHAEL89' in USERNAMES: 
    ... 

nơi USERNAMES là danh sách


Có cách nào để phù hợp với mục có trường hợp vô hồn hay tôi cần phải sử dụng một phương pháp tùy chỉnh? Chỉ cần tự hỏi nếu có cần phải viết thêm mã cho việc này.

Nhờ tất cả mọi người!

Trả lời

122
if 'MICHAEL89' in (name.upper() for name in USERNAMES): 
    ... 

Hoặc:

if 'MICHAEL89' in map(str.upper, USERNAMES): 
    ... 

Hoặc, có, bạn có thể tạo ra một phương pháp tùy chỉnh.

+6

'nếu 'CaseFudge'.lower() trong [x.lower() cho x trong danh sách]' – fredley

+32

'[...]' tạo ra toàn bộ danh sách. '(name.upper() cho tên trong USERNAMES)' sẽ chỉ tạo ra một máy phát và một chuỗi cần thiết tại một thời điểm - tiết kiệm bộ nhớ lớn nếu bạn đang thực hiện thao tác này rất nhiều. (thậm chí tiết kiệm nhiều hơn, nếu bạn chỉ cần tạo danh sách tên người dùng thường xuyên mà bạn sử dụng lại để kiểm tra mọi lúc) – viraptor

+2

Ưu tiên giảm tất cả các phím khi xây dựng dict, vì lý do hiệu suất. – Ryan

6

Tôi nghĩ bạn phải viết thêm một số mã. Ví dụ:

if 'MICHAEL89' in map(lambda name: name.upper(), USERNAMES): 
    ... 

Trong trường hợp này, chúng ta đang hình thành một danh sách mới với tất cả các mục trong USERNAMES chuyển đổi sang chữ hoa và sau đó so sánh với danh sách mới này.

Cập nhật

Như @viraptor nói, nó thậm chí còn tốt hơn để sử dụng một máy phát điện thay vì map. Xem @Nathon 's answer.

+0

Hoặc bạn có thể sử dụng hàm 'itertools'' imap'. Nó nhanh hơn nhiều so với một máy phát điện nhưng hoàn thành cùng một mục tiêu. – wheaties

4

Bạn có thể làm

matcher = re.compile('MICHAEL89', re.IGNORECASE) 
filter(matcher.match, USERNAMES) 

Cập nhật: chơi xung quanh một chút và đang nghĩ đến bạn có thể nhận được một đoạn ngắn mạch phương pháp loại tốt hơn sử dụng

matcher = re.compile('MICHAEL89', re.IGNORECASE) 
if any(ifilter(matcher.match, USERNAMES)): 
    #your code here 

Chức năng ifilter là từ itertools, một trong những các mô-đun yêu thích của tôi trong Python. Nó nhanh hơn máy phát điện nhưng chỉ tạo ra mục tiếp theo của danh sách khi được gọi.

+0

Chỉ cần thêm, mẫu có thể cần phải được thoát, vì nó có thể chứa các ký tự như ".", "?", Có ý nghĩa đặc biệt trong các mẫu biểu thức chính quy. sử dụng re.escape (raw_string) để làm điều đó –

15

Tôi sẽ tạo trình bao bọc để bạn có thể không xâm lấn. Tối thiểu, ví dụ ...:

class CaseInsensitively(object): 
    def __init__(self, s): 
     self.__s = s.lower() 
    def __hash__(self): 
     return hash(self.__s) 
    def __eq__(self, other): 
     # ensure proper comparison between instances of this class 
     try: 
      other = other.__s 
     except (TypeError, AttributeError): 
      try: 
      other = other.lower() 
      except: 
      pass 
     return self.__s == other 

Bây giờ, if CaseInsensitively('MICHAEL89') in whatever: nên cư xử theo yêu cầu (xem phía bên tay phải là một danh sách, dict, hoặc thiết lập). (Nó có thể đòi hỏi nhiều nỗ lực hơn để đạt được kết quả tương tự cho việc đưa vào chuỗi, tránh cảnh báo trong một số trường hợp liên quan đến unicode, v.v.).

+3

mà không hoạt động cho dict thử nếu CaseInsensitively ('MICHAEL89') trong {'Michael89': True}: in "tìm thấy" –

+2

Xavier: Bạn sẽ cần 'CaseInsensitively ('MICHAEL89 ') trong {CaseInsensitively (' Michael89 '): True} 'cho rằng để làm việc, mà có lẽ không thuộc" hành xử theo yêu cầu ". – Gabe

+0

Vì vậy, nhiều cho chỉ có 1 cách rõ ràng để làm điều đó. Điều này cảm thấy nặng nề, trừ khi nó sẽ được sử dụng rất nhiều. Điều đó nói rằng, nó rất trơn tru. – nmichaels

8

Thông thường (ít nhất là oop) bạn định hình đối tượng của mình để ứng xử theo cách bạn muốn. name in USERNAMES không phải là trường hợp nhạy cảm, vì vậy USERNAMES nhu cầu thay đổi:

class NameList(object): 
    def __init__(self, names): 
     self.names = names 

    def __contains__(self, name): # implements `in` 
     return name.lower() in (n.lower() for n in self.names) 

    def add(self, name): 
     self.names.append(name) 

# now this works 
usernames = NameList(USERNAMES) 
print someone in usernames 

Những điều tuyệt vời về việc này là nó sẽ mở ra con đường cho nhiều cải tiến, mà không cần phải thay đổi bất kỳ mã bên ngoài lớp. Ví dụ: bạn có thể thay đổi self.names thành bộ để tìm kiếm nhanh hơn hoặc chỉ tính (n.lower() for n in self.names) một lần và lưu trữ trên lớp và cứ như vậy ...

3

Dưới đây là một cách:

if string1.lower() in string2.lower(): 
    ... 
+2

AttributeError: đối tượng 'list' không có thuộc tính 'lower' – Jeff

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