Максимальные значения для частично совпадающих ключей в словаре Python

1

У меня есть следующий словарь, где ключи: "месяц, страна: идентификатор", а значения - это всего лишь:

ID_dict = {'11,United Kingdom:14416': 129.22, '11,United Kingdom:17001': 357.6, 
'12,United States:14035': 90000.0, '12,United Kingdom:17850': 241.16,'12,United 
States:14099': 90000.0, '12,France:12583': 252.0, '12,United Kingdom:13047': 
215.13, '01,Germany:12662': 78.0, '01,Germany:12600': 14000}

Фактический словарь будет намного больше, чем этот.

Я пытаюсь вернуть ключ для каждого месяца, страны, которая содержит самую высокую общую сумму. Если есть связь, идентификатор будет разделен запятой. Пример Результат, основанный на словаре выше:

'11,United Kingdom:17001'
'12,United Kingdom:17850'
'12,United States:14035, 14099'
'12,France:12583'
'01,Germany:12600'

Я могу получить строки наивысших значений, используя следующий код:

highest = max(ID_dict.values())
print([k for k, v in ID_dict.items() if v == highest])

Но действительно изо всех сил пытаюсь преодолеть этот момент. Я экспериментировал с использованием re.match и re.search, но не очень далеко от них.

  • 0
    Не проще ли использовать вложенные словари, а не комбинированные ключи, подобные этой?
  • 0
    @Barmar Barmar Я согласен, мне интересно, если OP возражает против реструктуризации dict или его данные уже настроены в этом формате, он сказал, что фактический диктат намного больше
Показать ещё 1 комментарий
Теги:
python-2.7

2 ответа

0

Следующий код создает новый словарь с ключами "месяц, страна" и списками (значение, IDnum) в качестве значений. Затем он сортирует каждый список и собирает все IDnums, которые соответствуют наивысшему значению.

ID_dict = {
    '11,United Kingdom:14416': 129.22, '11,United Kingdom:17001': 357.6, 
    '12,United States:14035': 90000.0, '12,United Kingdom:17850': 241.16,
    '12,United States:14099': 90000.0, '12,France:12583': 252.0, 
    '12,United Kingdom:13047': 215.13, '01,Germany:12662': 78.0, 
    '01,Germany:12600': 14000
}

# Create a new dict with 'month,country' keys 
# and lists of (value, IDnum) as the values
new_data = {}
for key, val in ID_dict.items():
    newkey, idnum = key.split(':')
    new_data.setdefault(newkey, []).append((val, idnum))

# Sort the values for each 'month,country' key,
# and get the IDnums corresponding to the highest values
for key, val in new_data.items():
    val = sorted(val, reverse=True)
    highest = val[0][0]
    # Collect all IDnums that have the highest value
    ids = []
    for v, idnum in val:
        if v != highest:
            break
        ids.append(idnum)
    print(key + ':' + ', '.join(ids))

выход

11,United Kingdom:17001
12,United States:14099, 14035
12,United Kingdom:17850
12,France:12583
01,Germany:12600
  • 0
    Ха-ха. Очень хорошо. Я ревную, должен привыкнуть использовать setdefault Я знал, что его нужно использовать здесь, гуглил, как реализовать это вчера вечером перед сном, потому что я хотел решить эту проблему и не мог выбросить это из головы. но ваши ответы и ссылки помогли намного больше
0

Вы можете найти максимум за каждый month, country пару стран, сохранить это соотношение в словаре. Затем создайте словарь, который имеет в качестве ключей пары (month, country) а в качестве значений - список IDs, имеющих значение, равное максимуму для этой пары (month, country):

import re

ID_dict = {'11,United Kingdom:14416': 129.22, '11,United Kingdom:17001': 357.6,
           '12,United States:14035': 90000.0, '12,United Kingdom:17850': 241.16, '12,United States:14099': 90000.0,
           '12,France:12583': 252.0, '12,United Kingdom:13047': 215.13, '01,Germany:12662': 78.0,
           '01,Germany:12600': 14000}

table = {tuple(re.split(',|:', key)[:2]): value for key, value in sorted(ID_dict.items(), key=lambda e: e[1])}

result = {}
for key, value in ID_dict.items():
    splits = re.split(',|:', key)
    if value == table[tuple(splits[:2])]:
        result.setdefault(tuple(splits[:2]), []).append(splits[2])

for key, value in result.items():
    print('{}:{}'.format(','.join(key), ', '.join(value)))

Выход

01,Germany:12600
12,United States:14099, 14035
12,United Kingdom:17850
11,United Kingdom:17001
12,France:12583

Вышеупомянутый подход - O (nlogn), потому что он использует sorted, чтобы сделать O (n), вы можете изменить понимание слова в этом цикле:

table = {}
for s, v in ID_dict.items():
    key = tuple(re.split(',|:', s)[:2])
    table[key] = max(table.get(key, v), v)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню