在循环数据时嵌套字典

Yen*_*the 5 python dictionary list indentation python-2.7

我有一个相当难的问题,我无法修复.想法是循环一部分数据并找到任何缩进.(总是空格)每当一行有比前一个更大的缩进时,例如4个以上的空格,第一行应该是字典的键,并且应该追加下一个值.

如果有另一个缩进,这意味着应该创建一个带有键和值的新词典.这应该是递归的,直到通过数据.为了使事情更容易理解,我做了一个例子:

Chassis 1:
    Servers:
        Server 1/1:
            Equipped Product Name: EEE UCS B200 M3
            Equiped PID: e63-samp-33
            Equipped VID: V01
            Acknowledged Cores: 16
            Acknowledged Adapters: 1
    PSU 1:
        Presence: Equipped
        VID: V00
        HW Revision: 0
Run Code Online (Sandbox Code Playgroud)

我们的想法是能够以字典形式返回任何数据部分.dictionary.get("Chassis 1:")应该返回所有数据,dictionary.get("Servers")应该返回比"Servers"行更深的缩进的所有内容.dictionary.get("PSU 1:")应该给{"PSU 1:":"Presence:Equipped","VID:100","HW Revision:0"}等等.我画了一个小方案来证明这一点,每种颜色都是另一种字典.

当缩进再次变深时,例如从8到4个空格,数据应该附加到具有较少缩进数据的字典.

我已尝试过代码,但它并没有出现在我想要的地方附近.

for item in Array:
    regexpatt = re.search(":$", item)
    if regexpatt:
        keyFound = True
        break

if not keyFound:
    return Array

#Verify if we still have lines with spaces
spaceFound = False
for item in Array:
    if item != item.lstrip():
        spaceFound = True
        break

if not spaceFound:
    return Array

keyFound = False
key=""
counter = -1
for item in Array:
    counter += 1
    valueTrim = item.lstrip()
    valueL = len(item)
    valueTrimL = len(valueTrim)
    diff = (valueL - valueTrimL)
    nextSame = False
    if item in Array:
        nextValue = Array[counter]
        nextDiff = (len(nextValue) - len(nextValue.lstrip()))
        if diff == nextDiff:
            nextSame = True


    if diff == 0 and valueTrim != "" and nextSame is True:
        match = re.search(":$", item)
        if match:
            key = item
            newArray[key] = []
            deptDetermine = True
            keyFound = True
    elif diff == 0 and valueTrim != "" and keyFound is False:
        newArray["0"].append(item)
    elif valueTrim != "":
        if depthDetermine:
            depth = diff
            deptDetermine = False
        #newValue = item[-valueL +depth]
        item = item.lstrip().rstrip()
        newArray[key].append(item)

for item in newArray:
    if item != "0":
        newArray[key] = newArray[key]

return newArray
Run Code Online (Sandbox Code Playgroud)

结果应该是这样的例如:

{
    "Chassis 1": {
        "PSU 1": {
            "HW Revision: 0", 
            "Presence: Equipped", 
            "VID: V00"
        }, 
        "Servers": {
            "Server 1/1": {
                "Acknowledged Adapters: 1", 
                "Acknowledged Cores: 16", 
                "Equiped PID: e63-samp-33", 
                "Equipped Product Name: EEE UCS B200 M3", 
                "Equipped VID: V01"
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望这足以解释这个概念

M4r*_*ini 4

这应该会给你你想要的嵌套结构。

如果您想要每个嵌套字典,也可以从根目录获取。取消注释if .. is not root部分

def parse(data):

    root = {}
    currentDict = root
    prevLevel = -1
    parents = []
    for line in data:
        if line.strip() == '': continue
        level = len(line) - len(line.lstrip(" "))
        key, value = [val.strip() for val in line.split(':', 1)]

        if level > prevLevel and not len(value):
            currentDict[key] = {}
            # if currentDict is not root:
            #     root[key] = currentDict[key]
            parents.append((currentDict, level))
            currentDict = currentDict[key]
            prevLevel = level
        elif level < prevLevel and not len(value):
            parentDict, parentLevel = parents.pop()
            while parentLevel != level:
                if not parents: return root
                parentDict, parentLevel = parents.pop()
            parentDict[key] = {}
            parents.append((parentDict, level))
            # if parentDict is not root:
            #     root[key] = parentDict[key]
            currentDict = parentDict[key]
            prevLevel = level
        else:
            currentDict[key] = value
    return root 




with open('data.txt', 'r') as f:
    data = parse(f)
    #for pretty print of nested dict
    import json
    print json.dumps(data,sort_keys=True, indent=4)
Run Code Online (Sandbox Code Playgroud)

输出:

{
    "Chassis 1": {
        "PSU 1": {
            "HW Revision": "0", 
            "Presence": "Equipped", 
            "VID": "V00"
        }, 
        "Servers": {
            "Server 1/1": {
                "Acknowledged Adapters": "1", 
                "Acknowledged Cores": "16", 
                "Equiped PID": "e63-samp-33", 
                "Equipped Product Name": "EEE UCS B200 M3", 
                "Equipped VID": "V01"
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 很好的解决方案!如果我能挑剔的话,我认为不需要使用 `str.count` 来测量 `level`,只需使用 `level = len(line) - len(line.lstrip(" "))`。如果键或值中存在“:”,此代码也会中断,但这并不奇怪(大多数解析器要求分隔符不存在于任一字段中),因此它可能更多地是给OP的注释。 (2认同)
  • @Yenthe 我做了编辑,现在它会跳过空行。看看是否有帮助。如果没有,按照亚当·斯密的建议将其放入 try 块中 (2认同)