从每个键具有多个唯一值的字符串列表创建一个 3 级字典

Create a 3 level dictionary from a list of strings with multiple uniqe values for each key

我有一个文本字符串列表,我需要从中构建一棵树,据我所知,实现这一点的正确数据结构是一个字典。 每个字符串的大小都是固定的,所有元素的格式都是相同的,因此不需要额外的检查。 列表的每条记录都是格式为 DD/MM/YYYY 的日期,年份 / 年应该在树的根部(键,这里没有重复),每年可能是多个月(内没有重复的月份)同一年)作为价值和每个月多天(同一个月内没有重复的日子)。

字符串列表示例:

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']}}

你不需要一棵树。您可以使用字典的字典,将列表作为最内层的值。

您可以使用 defaultdict 作为您的主要结构

result = defaultdict(defaultdict(list))

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

defaultdict 所做的是

  • 对于内部字典:你可以直接append。如果没有列表,则创建一个新的空列表。
  • for the outer dict: 同样,你可以参考键month假设已经有一个dict作为它的值。如果没有,则创建一个新的。

有多种方法可以实现这一点。您可以使用defaultdict from the collections module. But it can also be done use the plain dict.setdefault方法。

setdefault(key[, default])

If key is in the dictionary, return its value. If not, insert key with a value of default and return default. default defaults to None.

我们遍历数据,将其拆分为日、月和年字符串。然后我们在基础树中寻找年份键,如果它不存在我们为它创建一个新的空字典。然后我们在那个年份的字典中查找一个月份键,如果它不存在则为其创建一个新列表。最后,我们将日期字符串附加到月份列表。

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)

输出

{'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)