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

Python 从每个键具有多个uniqe值的字符串列表创建一个3级字典,python,python-3.x,dictionary,ordereddictionary,Python,Python 3.x,Dictionary,Ordereddictionary,我有一个文本字符串列表,我需要从中构建一个树,据我所知,实现这一点的正确数据结构是一个字典。 每个字符串的大小是固定的,所有元素的格式都是相同的,因此不需要进行额外的检查。 列表的每个记录都是DD/MM/YYYY格式的日期,年/年应位于树的根上(键,此处无重复项),每年的值可以是多个月(同年内无重复月),每个月的值可以是多天(同月内无重复天) 字符串列表的一个示例: 数据=['2018年2月4日'、'2018年2月5日'、'2018年2月6日'、'2018年3月1日', '10/03/2018'

我有一个文本字符串列表,我需要从中构建一个树,据我所知,实现这一点的正确数据结构是一个字典。 每个字符串的大小是固定的,所有元素的格式都是相同的,因此不需要进行额外的检查。 列表的每个记录都是DD/MM/YYYY格式的日期,年/年应位于树的根上(键,此处无重复项),每年的值可以是多个月(同年内无重复月),每个月的值可以是多天(同月内无重复天)

字符串列表的一个示例:

数据=['2018年2月4日'、'2018年2月5日'、'2018年2月6日'、'2018年3月1日', '10/03/2018', '08/09/2017', '09/09/2017', '11/10/2017', “2017年11月12日”、“2018年6月14日”、“2018年6月15日”、“2018年7月24日”、“2018年7月26日”、“2018年8月30日”、“2018年8月31日”、“2018年9月1日”]

除了一个解决方案,如果有任何可以提供我也想解释,以便理解

这是我到目前为止写的,显然是错误的,因为结果是一本只有最后两项的字典

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

你不需要一棵树。您可以使用dict的dict,将列表作为最里面的值

您可以使用
defaultdict
作为主结构

result = defaultdict(defaultdict(list))

for date in data:
    day, month, year = date.split('/')
    result[year][month].append(day)
默认dict的作用是

  • 对于内部命令:您可以直接
    追加
    。如果没有列表,将创建一个新的空列表
  • 对于外部dict:类似地,您可以引用键
    month
    ,假设已经有一个dict作为其值。如果没有,则创建一个新的

实现这一点有多种方法。您可以使用
集合
模块中的。但也可以使用简单的方法来完成

设置默认值(键[,默认值])

如果键在字典中,则返回其值。如果不是,则插入值为default的键并返回default。默认值为“无”

我们对数据进行循环,将其分为日、月和年字符串。然后我们在基础树中查找年份键,如果它不存在,我们将为它创建一个新的空dict。然后,我们在当年的dict中查找一个月键,如果它不存在,则为它创建一个新列表。最后,我们将日期字符串附加到月份列表中

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)

请添加您的代码,您面临的问题是什么?到目前为止,我没有任何可用的代码,但我可以发布我可耻的尝试。很好,这就是最好的方式。是的,这就是最终结果应该是什么样子,抱歉,我忘了发布它。“我需要构建一个树,我知道实现这一点的正确数据结构是一个字典。”不一定。树通常使用您自己的自定义数据结构(也可能由
dict
对象组成,但可能涉及其他对象)来实现。值应为“天”@blue\u注意:您运行了这个吗?因为我很确定不能在for中拆分列表对象statement@vash_the_stampede:当然错了。谢谢,edited。没问题,我在运行嵌套的defaultdict时也遇到了一个错误,它不允许内部defaultdict是可编辑的,也许我遗漏了一些有用的、易于阅读和理解的东西。我知道python一行程序是首选,但对于我的python水平来说,更长的方式是完美的。谢谢。我想让你看看这个,我正在解决它。我正在考虑使用.split(“:”)并设置一个dict,每个键的唯一性在
之前,然后从那里开始,检查它。我想你最好先检查一下值“day”是否在mlist中,然后再附加实际给出最终想要的结果。如果天不在mlist:mlist.append(day)@一点一点啊。我不知道你需要排除重复的天数。我以为你在说数据中永远不会有重复的日子。您的解决方案很好,但另一种选择是将日期存储在集合中而不是列表中,这将自动消除重复项,就像dict键消除重复的年份和月份一样。为此,您需要使用
set.add
方法,该方法相当于
list.append
。OTOH,集合是无序集合,可能不适合您的用例。@PM2Ring实际排序是用于最终目的的首选。还有一个关于pprint的问题,为什么只有一个dict是以树形打印的,而其他dict不是?我在一些较大的实际数据列表上尝试了该代码,我看到只有一个“分支”以树的形式展开,其余的则不是。