2010-07-21 71 views
19

我可以使用map來實現使用Python進行不區分大小寫的列表搜索。不區分大小寫的字典搜索?

a = ['xyz', 'wMa', 'Pma']; 

b = map(string.lower, a) 
if 'Xyz'.lower() in b: 
    print 'yes' 

我該怎麼用字典做同樣的事情?

我試過下面的代碼,但是ap有['a','b','c']的列表,而不是不區分大小寫的字典。

a = {'a':1, 'B':2, 'c':3} 
ap = map(string.lower, a) 
+0

您是否想要明確的解決方案我使用過的地圖---這是我第一次讀這個問題的方式。 – 2010-07-21 08:40:00

+1

請參閱[PEP-455](https://www.python.org/dev/peps/pep-0455/):這是計劃在Python 3.5中包含標準庫(作爲'collections.TransformDict',提供的轉換是'str.casefold'或類似的) – 2015-01-12 21:51:06

+0

[PEP-455最終被拒絕。](https://www.python.org/dev/peps/pep-0455/#rejection) – 2017-06-01 15:12:18

回答

30

注意的小寫版本,可能會丟失信息:例如,你會如何「病例不敏感「{'a': 23, 'A': 45}?!如果您所關心的是,其中一個關鍵是在字典或沒有(即不關心什麼值對應於它),然後做一個set代替 - 即

theset = set(k.lower() for k in thedict) 

(Python中的每個版本或者{k.lower() for k in thedict},如果你對你的代碼感到滿意,那麼你的代碼只能在Python 2.7或更高版本中工作,這是爲了一些純粹的裝飾語法糖;-),並且檢查if k.lower() in theset: ...

或者,你可以做一個包裝類,例如,可能是隻讀一個...:

import collections 

class CaseInsensitiveDict(collections.Mapping): 
    def __init__(self, d): 
     self._d = d 
     self._s = dict((k.lower(), k) for k in d) 
    def __contains__(self, k): 
     return k.lower() in self._s 
    def __len__(self): 
     return len(self._s) 
    def __iter__(self): 
     return iter(self._s) 
    def __getitem__(self, k): 
     return self._d[self._s[k.lower()]] 
    def actual_key_case(self, k): 
     return self._s.get(k.lower()) 

這將保持(實際上不改變原來的字典,所以所有的準確信息仍然可以在需要時檢索它)任意一個可能爲多個值的鍵值,這些鍵值由於不區分大小寫而「摺疊」爲單個鍵值,並提供字典的所有隻讀方法(僅限字符串鍵)加上一個actual_key_case方法返回用於任何給定字符串鍵的實際大小寫混合(或None,如果沒有該給定字符串鍵的大小寫改變匹配字典中的任何鍵)。

+0

非常好 - 這解決了一個問題我是有一個API在請求的字段名稱上進行不區分大小寫的匹配,但返回規範字段名稱,所以我會要求'email',但要獲得'Email'。這個字典讓我將其映射回我要求的字段名稱。結果! __getitem __()方法中的小錯字 – metadaddy 2011-11-22 08:51:39

+2

。 self_s_s而不是self_s。顯然我不能在SO中進行1個字符的編輯(必須> = 6)! – SteveJ 2012-05-07 22:47:39

+1

不完全是字典的替代品,請參閱完整的http://stackoverflow.com/a/27890005/99834 – sorin 2015-01-11 17:32:42

5
dict(zip(map(string.lower,a.keys()),a.values())) 

會做你要找的東西。

map(函數,可迭代)在迭代器上工作;並且字典的迭代是密鑰列表。

a = {'a': 1, 'c': 3, 'B': 2} 
for i in a: 
print a 
# returns a c B 

zip將鍵和值彙集到一起,但是作爲一系列元組。字典將元組轉換回字典。

你也可以做類似

def myfunc(t): 
return (string.lower(t[0]),t[1]) 

map(myfunc,a.items()) 
# returns [('a', 1), ('c', 3), ('b', 2) 
dict(map(myfunc,a.items())) 
# returns {'a': 1, 'c': 3, 'b': 2} 

或者,甚至更多的樂趣......

dict(map(lambda (key, value):(string.lower(key),value),a.items())) 
12

使用字典內涵(Python2.7 +)

a_lower = {k.lower():v for k,v in a.items()} 

如果你的python對於詞典理解來說太老了

a_lower = dict((k.lower(),v) for k,v in a.items()) 

再看看價值與製作字典不區分大小寫的,以任何均值的關鍵

value = a_lower[key.lower()] 
3

如果你不經常需要查找,你可以使用此函數而不浪費其他字典副本的空間。這是緩慢的,因爲所有的密鑰都必須每次檢查。

a = {'xyz':2, 'wMa':8, 'Pma':9} 

## if you do not use many times and/or the dict is very big 

def case_insensitive_key(a,k): 
    k = k.lower() 
    return [a[key] for key in a if key.lower() == k] 

print 'yes' if case_insensitive_key(a,'Xyz') else 'no' 
1

只想添加__setitem__,彈出亞歷馬爾泰利的答案:

from requests import CaseInsensitiveDict 

或者,如果你想看到的代碼:通過使用一個真正的不區分大小寫的字典

from collections import Mapping 

class CaseInsensitiveDict(Mapping): 
    def __init__(self, d): 
     self._d = d 
     self._s = dict((k.lower(), k) for k in d) 
    def __contains__(self, k): 
     return k.lower() in self._s 
    def __len__(self): 
     return len(self._s) 
    def __iter__(self): 
     return iter(self._s) 
    def __getitem__(self, k): 
     return self._d[self._s[k.lower()]] 
    def __setitem__(self, k, v): 
     self._d[k] = v 
     self._s[k.lower()] = k 
    def pop(self, k): 
     k0 = self._s.pop(k.lower()) 
     return self._d.pop(k0) 
    def actual_key_case(self, k): 
     return self._s.get(k.lower()) 
8

開始:

class CaseInsensitiveDict(dict): 

    """Basic case insensitive dict with strings only keys.""" 

    proxy = {} 

    def __init__(self, data): 
     self.proxy = dict((k.lower(), k) for k in data) 
     for k in data: 
      self[k] = data[k] 

    def __contains__(self, k): 
     return k.lower() in self.proxy 

    def __delitem__(self, k): 
     key = self.proxy[k.lower()] 
     super(CaseInsensitiveDict, self).__delitem__(key) 
     del self.proxy[k.lower()] 

    def __getitem__(self, k): 
     key = self.proxy[k.lower()] 
     return super(CaseInsensitiveDict, self).__getitem__(key) 

    def get(self, k, default=None): 
     return self[k] if k in self else default 

    def __setitem__(self, k, v): 
     super(CaseInsensitiveDict, self).__setitem__(k, v) 
     self.proxy[k.lower()] = k 
+5

現在它實際上在requests.structures中:http://docs.python-requests.org /en/v0.5.0/api/#structures – Gallaecio 2015-03-27 09:33:54