Python 不区分大小写的字典搜索?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3296499/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 10:18:59  来源:igfitidea点击:

Case insensitive dictionary search?

pythondictionary

提问by prosseek

I can use map to implement the case insensitive list search with Python.

我可以使用 map 用 Python 实现不区分大小写的列表搜索。

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

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

How can I do the same thing with dictionary?

我怎样才能用字典做同样的事情?

I tried the following code, but ap has the list of ['a','b','c'], not the case insensitive dictionary.

我尝试了以下代码,但 ap 具有 ['a','b','c'] 列表,而不是不区分大小写的字典。

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

采纳答案by Alex Martelli

Note that making a dictionary case-insensitive, by whatever mean, may well lose information: for example, how would you "case-insensitivize" {'a': 23, 'A': 45}?! If all you care is where a key is in the dict or not (i.e., don't care about what value corresponds to it), then make a setinstead -- i.e.

请注意,使字典不区分大小写,无论如何都可能会丢失信息:例如,您将如何“不区分大小写” {'a': 23, 'A': 45}?!如果你只关心一个键在字典中的位置(即,不关心它对应的值是什么),那么做一个set- 即

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

(in every version of Python, or {k.lower() for k in thedict}if you're happy with your code working only in Python 2.7 or later for the sake of some purely decorative syntax sugar;-), and check with if k.lower() in theset: ....

(在每个版本的 Python 中,或者{k.lower() for k in thedict}如果你对你的代码只在 Python 2.7 或更高版本中工作感到满意,为了一些纯粹的装饰性语法糖;-),并检查if k.lower() in theset: ....

Or, you could make a wrapper class, e.g., maybe a read-only one...:

或者,您可以创建一个包装类,例如,可能是只读的...:

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

This will keep (without actually altering the original dictionary, so all precise information can still be retrieve for it, if and when needed) an arbitrary one of possibly-multiple values for keys that "collapse" into a single key due to the case-insensitiveness, and offer all read-only methods of dictionaries (with string keys, only) plus an actual_key_casemethod returning the actual case mix used for any given string key (or Noneif no case-alteration of that given string key matches any key in the dictionary).

这将保留(实际上不改变原始字典,因此仍然可以在需要时为其检索所有精确信息)可能的多个键值中的任意一个“折叠”为单个键的键值 -不敏感,并提供字典的所有只读方法(仅带有字符串键)以及actual_key_case返回用于任何给定字符串键的实际大小写组合的方法(或者None如果该给定字符串键的大小写更改不匹配字典中的任何键) )。

回答by Rizwan Kassim

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

will do what you're looking for.

会做你正在寻找的。

map(function,iterable) works over the iterable; and iterable of the dictionary is the list of keys.

map(function,iterable) 在迭代器上工作;字典的迭代是键列表。

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

zip brings together the keys and values back into pairs, but as a series of tuples. dict converts the tuples back into a dict.

zip 将键和值重新组合成对,但作为一系列元组。dict 将元组转换回 dict。

You could also do something like

你也可以做类似的事情

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}

Or, even more fun...

或者,更有趣...

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

回答by John La Rooy

Using dict comprehensions (Python2.7+)

使用字典推导式 (Python2.7+)

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

If your python is too old for dict comprehensions

如果你的 python 太旧而无法理解字典

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

then look up the value with the lowercase version of the key

然后使用键的小写版本查找值

value = a_lower[key.lower()]

回答by Tony Veijalainen

If you are not needing the lookup very often you can use this function without wasting space for other copy of dictionary. It is slow though as all keys must be checked against every time.

如果您不经常需要查找,则可以使用此功能而不会浪费空间用于其他字典副本。尽管每次都必须检查所有密钥,但速度很慢。

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'

回答by rabin utam

Just wanted to add __setitem__, pop to Alex Martelli's Answer:

只是想添加 __setitem__, pop 到 Alex Martelli 的答案:

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

回答by sorin

Start using a real case insensitive dictionary via:

通过以下方式开始使用真正的不区分大小写的字典:

from requests.structures import CaseInsensitiveDict

Or if you want to see the code:

或者,如果您想查看代码:

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