根据层次结构创建列表数

时间:2015-12-03 15:06:55

标签: python data-structures

我想要做的是将定义层次结构的表转换为多个列表(或字典或其他)

以下是我的源数据:

THING     THINGS_PARENT
100       None
200       100
300       200
400       100
500       None
600       300

稍微扩展一下以包括每个THING的级别(从一开始我不知道级别是什么)

THING     THINGS_PARENT   LEVEL
-----     -------------   -----
100       None            1
200       100             2
300       200             3
400       100             2
500       None            1
600       300             4

我最想要的是

level1list = [100, 500]
level2list = [200, 400]
level3list = [300]
level4list = [600]

我正在努力的事实是,物品清单可能是1或10,000,等级数可能是1到未知。

感谢您的期待

修改

所以我一直在研究这个问题,这就是我要做的事情:

parentdict = {100: None, 200: 100, , 300: 200, 400: 100, 500: None, 600:300}
levelcount = 1
templist = []
for thing, parent in parentdict.iteritems():
    if parent is None:
        templist.append(thing)
levelsdict[levelcount] = templist

现在我无法弄清楚如何迭代字典,直到我拥有了我需要的所有列表。

3 个答案:

答案 0 :(得分:1)

更多信息后的解决方案

即使没有限制输入的呈现方式,以下解决方案也应该有效。

parentdict = {100: 200, 200: None, 300: 200, 400: 150, 500: None, 600: 300, 150: 100}
from collections import defaultdict
leveldict = defaultdict(int)
levellistdict = defaultdict(list)

def get_level(thing):
    if thing in leveldict:
        return leveldict[thing]
    elif parentdict[thing] == None:
        leveldict[thing] = 1
    else:
        parent_level = get_level(parentdict[thing])
        leveldict[thing] = 1 + parent_level
    return leveldict[thing]

for key in parentdict:
    leveldict[key] = get_level(key)
    levellistdict[leveldict[key]].append(key)

print leveldict
>> defaultdict(<type 'int'>, {100: 2, 200: 1, 300: 2, 400: 4, 500: 1, 150: 3, 600: 3})
print levellistdict
>> defaultdict(<type 'list'>, {1: [200, 500], 2: [100, 300], 3: [150, 600], 4: [400]})

@Peter它比你发布的解决方案好一点,因为get_level函数使用它先前计算过的信息。如果我已经计算了我的父级别,我可以使用它来计算我的级别而不是一直遍历以找到根元素(父级为None)。你的解决方案也很完美,但是当你拥有更多关卡时,这个解决方案会更快,更好。让我知道这是如何工作的。

编辑前的解决方案

对于玩具示例,你有这样的东西可以解决你的目的:

parentdict = {100: None, 200: 100, 300: 200, 400: 100, 500: None, 600:300}
from collections import defaultdict
leveldict = defaultdict(int)
levellistdict = defaultdict(list)
for key in parentdict:
    if parentdict[key] == None:
        leveldict[key] = 1
        levellistdict[1].append(key)
    else:
        level = leveldict[parentdict[key]] + 1
        leveldict[key] = level
        levellistdict[level].append(key)

print leveldict
>> defaultdict(<type 'int'>, {100: 1, 200: 2, 300: 3, 400: 2, 500: 1, 600: 4})
print levellistdict
>> defaultdict(<type 'list'>, {1: [100, 500], 2: [200, 400], 3: [300], 4: [600]})

该解决方案保留两个dicts,一个用于每个THING的LEVEL,另一个用于每个LEVEL的列表。对于任何新项目 - 如果其父项为None,我们分配级别1,如果不是,我们将1添加到父级别并附加到适当的列表。

请注意,这假设dict中THING的顺序是THINGS_PARENT总是在THING之前发生。根据您加载数据的方式,如果需要,可以使用OrderedDict确保这一点。我会留给你弄清楚的。

答案 1 :(得分:1)

我已经弄明白了答案,但我相信它可能更加pythonic。这是我的答案,请随时改进:

parentdict = {100: None, 200: 100, 300: 200, 400: 100, 500: None, 600: 300}
def getParent(p_child):
    level = 1
    thisparent = parentdict[p_child]
    while thisparent is not None:
        thisparent = parentdict[thisparent]
        level += 1
    return level



levelsdict = {}
for thing in parentdict.keys():
    thinglevel = getParent(thing)
    if thinglevel in levelsdict:
        templist = levelsdict[thinglevel]
        templist.append(thing)
        levelsdict[thinglevel] = templist
    else:
        levelsdict[thinglevel] = [thing]

print levelsdict

{1: [100, 500],2: [200,400], 3: [300], 4: [600]}

答案 2 :(得分:0)

我会使用2维列表。如果您不知道二维列表是列表中的列表。

假设您解析每行文本并将其存储在变量currLine中,您可以这样做:

level = currLine.split()[2]

这样做是分开一行,如:

  

&#34; 100无1&#34;

  

[&#34; 100&#34;&#34;无&#34;&#34; 1&#34;]

在您完成之后,您将访问该列表的第3个元素,或索引2,即级别并将其存储在level变量中。现在您可以划一条线并确定其级别,您可以遍历表格中的每一行并告诉它是什么级别。

这部分效率低下但我无法想到另一种方法。希望另一个用户可以评论一种优化方法,但是你需要遍历你的表两次,一次找到最大值,另一次存储值。 假设您发现最高级别为5,则可以使用该级别创建主列表。

masterList = [[]] * 5

这会创建一个如下列表:

  

[[],[],[],[],[]]

基本上它的作用是在一个大列表中创建5个列表。现在,您可以再次遍历表,找出对象的级别,然后将其添加到masterList的索引

level = currLine.split()[2]
masterList[level].append(currLine.split()[0])

例如,如果你选择&#34; 100无1&#34;,你将它分成[&#34; 100&#34;,&#34;无&#34;,&#34; 1&#34 ;],将其第3个元素存储在level中,然后将第一个元素(&#34; 100&#34;)附加到master的第1个列表中。这会将masterList更新为:

  

[[&#34; 100&#34],[],[],[],[]]

循环遍历所有文本文件并根据级别将它们存储在masterList中之后,您可以稍后将每个master列表存储到另一个列表中。

level1list = masterList[0]
level2list = masterList[1]
...
level5list = masterList[4]

由于列表的工作原理,它应该注意到masterList的索引比级别少一个。我希望这有帮助。祝彼此好运!