대소 문자를 구분하지 않는 사전
내 사전이 대소 문자를 구분하지 않기를 바랍니다.
이 예제 코드가 있습니다.
text = "practice changing the color"
words = {'color': 'colour',
'practice': 'practise'}
def replace(words,text):
keys = words.keys()
for i in keys:
text= text.replace(i ,words[i])
return text
text = replace(words,text)
print text
출력 = 색상 변경 연습
동일한 출력을 제공하기 위해 다른 문자열,, "practice changing the Color"( Color대문자 로 시작하는 곳 )을 원합니다 .
사용하여 소문자로 변환하는 일반적인 방법이 있다고 생각 mydictionary[key.lower()]하지만이를 기존 코드에 가장 잘 통합하는 방법을 모르겠습니다. (어쨌든 이것이 합리적이고 간단한 접근법이라면).
내가 당신을 올바르게 이해하고 대소 문자를 구분하지 않는 방식으로 사전을 키우는 방법을 원한다면 한 가지 방법은 dict를 하위 클래스로 만들고 setter / getter를 오버로드하는 것입니다.
class CaseInsensitiveDict(dict):
def __setitem__(self, key, value):
super(CaseInsensitiveDict, self).__setitem__(key.lower(), value)
def __getitem__(self, key):
return super(CaseInsensitiveDict, self).__getitem__(key.lower())
현재 승인 된 대답은 작동하지 않습니다 많은 이 드롭 인으로 사용할 수 없습니다, 그래서 경우 dict교체. 적절한 dict교체 를위한 몇 가지 까다로운 점 :
- 키와 관련된 모든 메서드 오버로드
- 문자열이 아닌 키를 올바르게 처리
- 클래스의 생성자를 적절하게 처리
다음이 훨씬 더 잘 작동합니다.
class CaseInsensitiveDict(dict):
@classmethod
def _k(cls, key):
return key.lower() if isinstance(key, basestring) else key
def __init__(self, *args, **kwargs):
super(CaseInsensitiveDict, self).__init__(*args, **kwargs)
self._convert_keys()
def __getitem__(self, key):
return super(CaseInsensitiveDict, self).__getitem__(self.__class__._k(key))
def __setitem__(self, key, value):
super(CaseInsensitiveDict, self).__setitem__(self.__class__._k(key), value)
def __delitem__(self, key):
return super(CaseInsensitiveDict, self).__delitem__(self.__class__._k(key))
def __contains__(self, key):
return super(CaseInsensitiveDict, self).__contains__(self.__class__._k(key))
def has_key(self, key):
return super(CaseInsensitiveDict, self).has_key(self.__class__._k(key))
def pop(self, key, *args, **kwargs):
return super(CaseInsensitiveDict, self).pop(self.__class__._k(key), *args, **kwargs)
def get(self, key, *args, **kwargs):
return super(CaseInsensitiveDict, self).get(self.__class__._k(key), *args, **kwargs)
def setdefault(self, key, *args, **kwargs):
return super(CaseInsensitiveDict, self).setdefault(self.__class__._k(key), *args, **kwargs)
def update(self, E={}, **F):
super(CaseInsensitiveDict, self).update(self.__class__(E))
super(CaseInsensitiveDict, self).update(self.__class__(**F))
def _convert_keys(self):
for k in list(self.keys()):
v = super(CaseInsensitiveDict, self).pop(k)
self.__setitem__(k, v)
기록만을 위해서. Requests 에 대한 굉장한 추진력을 찾았습니다 .
https://github.com/kennethreitz/requests/blob/v1.2.3/requests/structures.py#L37
string.lower()입력에 사용하고 완전히 소문자 사전을 사용하는 것을 고려 하시겠습니까 ? 약간의 해키 솔루션이지만 작동합니다.
특정 경우에는 대소 문자를 구분하지 않는 조회가 필요했지만 키의 원래 대소 문자를 수정하고 싶지 않았습니다. 예를 들면 :
>>> d = {}
>>> d['MyConfig'] = 'value'
>>> d['myconfig'] = 'new_value'
>>> d
{'MyConfig': 'new_value'}
사전에 여전히 원래 키가 있지만 대소 문자를 구분하지 않고 액세스 할 수 있음을 알 수 있습니다. 다음은 간단한 해결책입니다.
class CaseInsensitiveKey(object):
def __init__(self, key):
self.key = key
def __hash__(self):
return hash(self.key.lower())
def __eq__(self, other):
return self.key.lower() == other.key.lower()
def __str__(self):
return self.key
__hash__ 및 __eq__ 재정의는 사전에서 항목을 가져오고 설정하는 데 필요합니다. 이것은 대소 문자를 구분하지 않고 동일한 경우 사전의 동일한 위치로 해시하는 키를 생성합니다.
이제 제공된 키를 사용하여 CaseInsensitiveKey를 초기화하는 사용자 지정 사전을 만들 수 있습니다.
class CaseInsensitiveDict(dict):
def __setitem__(self, key, value):
key = CaseInsensitiveKey(key)
super(CaseInsensitiveDict, self).__setitem__(key, value)
def __getitem__(self, key):
key = CaseInsensitiveKey(key)
return super(CaseInsensitiveDict, self).__getitem__(key)
또는 단순히 사전을 사용할 때 항상 CaseInsensitiveKey 인스턴스를 키로 전달해야합니다.
대소 문자를 구분하지 않는 사전이 해결책이고이를 달성하는 방법에 대한 답변이 있지만이 경우에는 더 쉬운 방법이 있습니다. 대소 문자를 구분하지 않는 검색으로 충분합니다.
import re
text = "Practice changing the Color"
words = {'color': 'colour', 'practice': 'practise'}
def replace(words,text):
keys = words.keys()
for i in keys:
exp = re.compile(i, re.I)
text = re.sub(exp, words[i], text)
return text
text = replace(words,text)
print text
pleasemorebacon (감사합니다!)에 의해 간단하지만 좋은 솔루션을 수정하여 약간 더 컴팩트하고 독립적이며 약간의 업데이트로 프로토콜을 구성 {'a':1, 'B':2}하고 지원할 수 __contains__있습니다. 마지막으로 CaseInsensitiveDict.Key는 문자열이어야하므로 (그 밖의 것은 대소 문자를 구분할 수 있는지 여부)에서 Key클래스 를 파생하는 것이 좋습니다. str예를 들어 상자 CaseInsensitiveDict에서 json.dumps꺼내서 덤프 할 수 있습니다.
# caseinsensitivedict.py
class CaseInsensitiveDict(dict):
class Key(str):
def __init__(self, key):
str.__init__(key)
def __hash__(self):
return hash(self.lower())
def __eq__(self, other):
return self.lower() == other.lower()
def __init__(self, data=None):
super(CaseInsensitiveDict, self).__init__()
if data is None:
data = {}
for key, val in data.items():
self[key] = val
def __contains__(self, key):
key = self.Key(key)
return super(CaseInsensitiveDict, self).__contains__(key)
def __setitem__(self, key, value):
key = self.Key(key)
super(CaseInsensitiveDict, self).__setitem__(key, value)
def __getitem__(self, key):
key = self.Key(key)
return super(CaseInsensitiveDict, self).__getitem__(key)
다음은 실제 상황을 확인하려는 사용자를위한 기본 테스트 스크립트입니다.
# test_CaseInsensitiveDict.py
import json
import unittest
from caseinsensitivedict import *
class Key(unittest.TestCase):
def setUp(self):
self.Key = CaseInsensitiveDict.Key
self.lower = self.Key('a')
self.upper = self.Key('A')
def test_eq(self):
self.assertEqual(self.lower, self.upper)
def test_hash(self):
self.assertEqual(hash(self.lower), hash(self.upper))
def test_str(self):
self.assertEqual(str(self.lower), 'a')
self.assertEqual(str(self.upper), 'A')
class Dict(unittest.TestCase):
def setUp(self):
self.Dict = CaseInsensitiveDict
self.d1 = self.Dict()
self.d2 = self.Dict()
self.d1['a'] = 1
self.d1['B'] = 2
self.d2['A'] = 1
self.d2['b'] = 2
def test_contains(self):
self.assertIn('B', self.d1)
d = self.Dict({'a':1, 'B':2})
self.assertIn('b', d)
def test_init(self):
d = self.Dict()
self.assertFalse(d)
d = self.Dict({'a':1, 'B':2})
self.assertTrue(d)
def test_items(self):
self.assertDictEqual(self.d1, self.d2)
self.assertEqual(
[v for v in self.d1.items()],
[v for v in self.d2.items()])
def test_json_dumps(self):
s = json.dumps(self.d1)
self.assertIn('a', s)
self.assertIn('B', s)
def test_keys(self):
self.assertEqual(self.d1.keys(), self.d2.keys())
def test_values(self):
self.assertEqual(
[v for v in self.d1.values()],
[v for v in self.d2.values()])
하나의 라이너로 dict 키 대소 문자를 구분하지 않는 검색을 수행 할 수 있습니다.
>>> input_dict = {'aBc':1, 'xyZ':2}
>>> search_string = 'ABC'
>>> next((value for key, value in input_dict.items() if key.lower()==search_string.lower()), None)
1
>>> search_string = 'EFG'
>>> next((value for key, value in input_dict.items() if key.lower()==search_string.lower()), None)
>>>
이를 함수에 넣을 수 있습니다.
def get_case_insensitive_key_value(input_dict, key):
return next((value for dict_key, value in input_dict.items() if dict_key.lower() == key.lower()), None)
Note that only the first match is returned.
If you only need to do this once in your code (hence, no point to a function), the most straightforward way to deal with the problem is this:
lowercase_dict = {key.lower(): value for (key, value) in original_dict}
I'm assuming here that the dict in question isn't all that large--it might be inelegant to duplicate it, but if it's not large, it isn't going to hurt anything.
The advantage of this over @Fred's answer (though that also works) is that it produces the same result as a dict when the key isn't present: a KeyError.
I just set up a function to handle this:
def setLCdict(d, k, v):
k = k.lower()
d[k] = v
return d
myDict = {}
So instead of
myDict['A'] = 1
myDict['B'] = 2
You can:
myDict = setLCdict(myDict, 'A', 1)
myDict = setLCdict(myDict, 'B', 2)
You can then either lower case the value before looking it up or write a function to do so.
def lookupLCdict(d, k):
k = k.lower()
return d[k]
myVal = lookupLCdict(myDict, 'a')
Probably not ideal if you want to do this globally but works well if its just a subset you wish to use it for.
참고URL : https://stackoverflow.com/questions/2082152/case-insensitive-dictionary
'Program Club' 카테고리의 다른 글
| EventEmitter angular2에 2 개의 매개 변수를 전달하는 방법 (0) | 2020.11.29 |
|---|---|
| C ++ 단위 테스트 프레임 워크 (0) | 2020.11.29 |
| javascript 문자열을 html 객체로 변환 (0) | 2020.11.29 |
| Find () 및 First ()는 예외를 throw합니다. 대신 null을 반환하는 방법은 무엇입니까? (0) | 2020.11.29 |
| 열에 항목을 정렬하기 위해 열 X까지 공백을 삽입하는 방법은 무엇입니까? (0) | 2020.11.29 |