Создайте трехуровневый словарь из списка строк с несколькими уникальными значениями для каждого ключа - PullRequest
0 голосов
/ 23 сентября 2018

У меня есть список текстовых строк, из которых мне нужно построить дерево, и, насколько я понимаю, правильная структура данных для достижения этой цели - словарь.Размер каждой строки фиксированный, а формат всех элементов одинаков, поэтому никаких дополнительных проверок не требуется.Каждая запись списка представляет собой дату в формате ДД / ММ / ГГГГ, и год / годы должны быть в корне дерева (ключи, здесь нет дубликатов), для каждого года может быть несколько месяцев (в течение месяца не должно быть повторяющихся месяцев).в тот же год) в качестве значения и за каждый месяц несколько дней (без повторяющихся дней в одном и том же месяце).

Пример списка строк:

data = ['04 / 02/ 2018 ', '05 / 02/2018', '06 / 02/2018 ', '01 / 03/2018', '10 / 03/2018 ', '08 / 09/2017', '09 / 09/2017', '11 / 10/2017', '11 / 12/2017 ', '14 / 06/2018', '15 / 06/2018 ', '24 / 07/2018', '26 / 07/2018 ','30 / 08/2018 ', '31 / 08/2018', '01 / 09/2018 ']

Помимо решения, если оно может быть предоставлено, я хотел бы также пояснить, чтобыпонимаю.

Это то, что я написал до сих пор, что явно неверно, поскольку в результате получается словарь, содержащий только последние 2 элемента.

d = {}
for item in data:
    rec = item.split('/')
    d.update({rec[2]:{rec[1]:(rec[0])}})

Требуемый вывод для этих данных выглядит следующим образом:

{'2017': {'09': ['08', '09'], '10': ['11'], '12': ['11']},
 '2018': {'02': ['04', '05', '06'],
          '03': ['01', '10'],
          '06': ['14', '15'],
          '07': ['24', '26'],
          '08': ['30', '31'],
          '09': ['01']}}

Ответы [ 2 ]

0 голосов
/ 23 сентября 2018

Существуют различные способы достижения этого.Вы можете использовать defaultdict из модуля collections.Но это также может быть сделано с использованием простого dict.setdefault метода.

setdefault(key[, default])

Если ключ есть в словаре, вернуть его значение.Если нет, вставьте ключ со значением default и верните default . по умолчанию по умолчанию Нет .

Мы зациклим данные, разбив их на строки дня, месяца и года.Затем мы ищем в базовом дереве ключ года, и, если он не существует, мы создаем для него новый пустой элемент.Затем мы смотрим в ключе год для ключа месяца, создавая новый список для него, если он не существует.Наконец, мы добавляем строку дня к списку месяцев.

from pprint import pprint

data = [
    '04/02/2018', '05/02/2018', '06/02/2018', '01/03/2018', '10/03/2018', '08/09/2017', '09/09/2017',
    '11/10/2017', '11/12/2017', '14/06/2018', '15/06/2018', '24/07/2018', '26/07/2018', '30/08/2018',
    '31/08/2018', '01/09/2018'
]

tree = {}

for s in data:
    day, mon, year = s.split('/')
    ydict = tree.setdefault(year, {})
    mlist = ydict.setdefault(mon, [])
    mlist.append(day)

pprint(tree)

output

{'2017': {'09': ['08', '09'], '10': ['11'], '12': ['11']},
 '2018': {'02': ['04', '05', '06'],
          '03': ['01', '10'],
          '06': ['14', '15'],
          '07': ['24', '26'],
          '08': ['30', '31'],
          '09': ['01']}}

Мы можем объединить 3 шага основного цикла в одну строку,но это немного сложнее читать:

for s in data:
    day, mon, year = s.split('/')
    tree.setdefault(year, {}).setdefault(mon, []).append(day)
0 голосов
/ 23 сентября 2018

Вам не нужно дерево.Вы можете использовать dict of dicts, имея списки в качестве внутренних значений.

Вы можете использовать defaultdict в качестве основной структуры

result = defaultdict(defaultdict(list))

for date in data:
    day, month, year = date.split('/')
    result[year][month].append(day)

Что делает defaultdict в том, что

  • для внутреннего диктанта: вы можетеappend напрямую.Если списка нет, создается новый пустой.
  • для внешнего dict: аналогично, вы можете ссылаться на ключ month, предполагая, что в качестве его значения уже существует dict.Если нет, создается новый.
...