Делая словарь Python нечувствительным к регистру, агрегируя ключи
У меня есть словарь с большим количеством ключей, которые отличаются друг от друга из-за чувствительности к регистру словаря. Я бы хотел, чтобы все это было в одной строчной клавише, но со всеми значениями этих ключей.
У меня есть что-то вроде:
>>> data
{'Blue Car': 73, 'blue Car': 21, 'yellow car': 10, 'Yellow Car': 15, 'Red Car': 12, 'Red car': 17, 'red car': 10, 'Yellow car': 18}
И вывод должен быть таким:
>>> newData
{'blue car': 94, 'yellow car': 43, 'red car': 39}
5 ответов
Использование словарей и набор понятий:
>>> {x: sum(v for k, v in data.items() if k.lower()==x) for x in set(map(lambda x: x.lower(), data))}
{'red car': 39, 'blue car': 94, 'yellow car': 43}
или более удобный для пользователя:
SET = set(map(lambda x: x.lower(), data))
SUM = lambda x: sum(v for k, v in data.items() if k.lower()==x)
newData = {x: SUM(x) for x in SET}
# newData = {'red car': 39, 'blue car': 94, 'yellow car': 43}
Разъяснение:
SET = set(map(lambda x: x.lower(), data))
получает все уникальные строчные ключи,
SUM = lambda x: sum(v for k, v in data.items() if k.lower()==x)
возвращает сумму значений для ключей в data
сопоставление уникального ключа и
{x: SUM(x) for x in SET}
будет сопоставлять это значение как часть пары с соответствующим ключом для каждого ключа в наборе.
Использовать defaultdict:
from collections import defaultdict
newData = defaultdict(int)
for k in data:
newData[k.lower()]+=data.get(k,0)
# {'blue car': 94, 'red car': 39, 'yellow car': 43}
Надеюсь, это поможет.
Попробуй это
def compress(data):
newDict = dict()
for key in data:
newDict[key.lower()] = newDict.get(key.lower(), default=0) + data[key]
return newDict
Как насчет использования defaultdict
:
from collections import defaultdict
newData = defaultdict(int)
for k,v in data.iteritems():
newData[k.lower()] += v
Я бы подкласс dict
и переопределить __getitem__
а также __setitem__
магические методы
class NormalizedDict(dict):
def __getitem__(self,key):
return dict.__getitem__(self,key.lower())
def __setitem__(self,key,value):
return dict.__setitem__(self,key.lower(),value)
myDict = NormalizedDict()
myDict['aPPles'] =5
print myDict
конечно мы можем взять это дальше и автосум для вас
class NormalizedSumDict(NormalizedDict):
def __setitem__(self,key,value):
if key.lower() in self and type(self[key]) == type(value):
try:
value = value + self[key]
except:
pass
NormalizedDict.__setitem__(self,key,value)
def update(self,other):
for k,v in other.items():
self[k] = v
d = NormalizedSumDict()
d['aPPles']=5
d['Apples']=2
print d