Делая словарь 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
Другие вопросы по тегам