【问题标题】:Convert python string with newlines and tabs to dictionary将带有换行符和制表符的python字符串转换为字典
【发布时间】:2016-02-05 08:22:03
【问题描述】:

我对我遇到的这个特殊问题有点困惑。我有一个可行的解决方案,但我认为它不是 Pythonic。

我有一个这样的原始文本输出:

Key 1   
  Value 1 
Key 2   
  Value 2 
Key 3   
  Value 3a  
  Value 3b
  Value 3c 
Key 4   
  Value 4a  
  Value 4b

我正在尝试制作字典:

{ 'Key 1': ['Value 1'], 'Key 2': ['Value 2'], 'Key 3': ['Value 3a', 'Value 3b', 'Value 3c'], 'Key 4': ['Value 4a', 'Value 4b'] }

原始输出可以变成一个字符串,它看起来像这样:

my_str = "
Key 1\n\tValue 1
\nKey 2\n\tValue 2
\nKey 3\n\tValue 3a \n\tValue 3b \n\tValue 3c
\nKey 4\n\tValue 4a \n\tValue 4b "

所以 Values 由 \n\t 分隔,而 Keys 由 \n 分隔

如果我尝试做这样的事情:

dict(item.split('\n\t') for item in my_str.split('\n'))

它没有正确解析它,因为它也在 \n\t 中拆分了“n”。

到目前为止,我有这样的事情:

#!/usr/bin/env python

str = "Key 1\n\tValue 1\nKey 2\n\tValue 2\nKey 3\n\tValue 3a \n\tValue 3b \n\tValue 3c\nKey 4\n\tValue 4a \n\tValue 4b"

output = str.replace('\n\t', ',').replace('\n',';')
result = {}
for key in output.split(';'):
  result[key.split(',')[0]] = key.split(',')[1:]
print result

返回:

{'Key 1': ['Value 1'], 'Key 2': ['Value 2'], 'Key 3': ['Value 3a ', 'Value 3b ', 'Value 3c'], 'Key 4': ['Value 4a ', 'Value 4b']}

但是,这对我来说看起来很恶心,我只是想知道是否有一种 Python 的方式来做到这一点。任何帮助将不胜感激!

【问题讨论】:

  • 我看到你现在自己找到了它。你现在问它是“Pythonic”。它有效吗?如果是这样,那么,谁在乎呢?

标签: python string dictionary split


【解决方案1】:

包括电池 - defaultdict 处理自动水合新键的值作为列表,我们利用 striswhitespace 方法检查缩进(否则我们可以使用正则表达式):

from collections import defaultdict

data = """
Key 1   
  Value 1 
Key 2   
  Value 2 
Key 3   
  Value 3a  
  Value 3b
  Value 3c 
Key 4   
  Value 4a  
  Value 4b
"""

result = defaultdict(list)
current_key = None

for line in data.splitlines():
    if not line: continue  # Filter out blank lines

    # If the line is not indented then it is a key
    # Save it and move on
    if not line[0].isspace():
        current_key = line.strip()
        continue

    # Otherwise, add the value
    # (minus leading and trailing whitespace)
    # to our results
    result[current_key].append(line.strip())

# result is now a defaultdict
defaultdict(<class 'list'>,
    {'Key 1': ['Value 1'],
     'Key 2': ['Value 2'], 
     'Key 3': ['Value 3a', 'Value 3b', 'Value 3c'],
     'Key 4': ['Value 4a', 'Value 4b']})

【讨论】:

  • 或者,您可以将result 设为常规字典,然后将result[current_key].append(line.strip()) 更改为result.setdefault(current_key, []).append(line.strip())。 (我经常使用collections.defaultdict,但有时我想知道它的用处,因为我使用它的目的只是为了避免单次调用setdefault。)
【解决方案2】:

itertools.groupby 在这里很有用。您可以按缩进对相邻行进行分组,然后使用extend 一次性将相邻的缩进行插入到字典中:

my_str = """Key 1\n\tValue 1\nKey 2\n\tValue 2\nKey 3\n\tValue 3a \n\tValue 3b \n\tValue 3c\nKey 4\n\tValue 4a \n\tValue 4b"""

def get_indent(line):
    return len(line) - len(line.lstrip())

res = {}
for indent, tokens in itertools.groupby(my_str.splitlines(), lambda line: get_indent):
    if indent == 0:
        cur_key = list(tokens)[0]
        res[cur_key] = []
    else:
        res[cur_key].extend( token.strip() for token in tokens )

print(res)
{'Key 3': ['Value 3a', 'Value 3b', 'Value 3c'],
 'Key 4': ['Value 4a', 'Value 4b'],
 'Key 2': ['Value 2'],
 'Key 1': ['Value 1']}

【讨论】:

    【解决方案3】:

    我发现,每当一个人开始在一行中将一堆操作链接在一起时(如在“result.setdefault...”行中),你就会混淆可能非常简单的问题。

    str = "Key 1\n\tValue 1\nKey 2\n\tValue 2\nKey 3\n\tValue 3a \n\tValue 3b \n\tValue 3c\nKey 4\n\tValue 4a \n\tValue 4b"
    
    output = str.replace('\n\t', ',').replace('\n',';')
    result = {}
    for group in output.split(';'):
        values = group.split(',')
        key = values[0]
        result[key] = []
        for v in values[1:]:
            result[key].append(v)
    print result
    

    产量:

    {'Key 1': ['Value 1'], 'Key 2': ['Value 2'], 'Key 3': ['Value 3a ', 'Value 3b ', 'Value 3c'], 'Key 4': ['Value 4a ', 'Value 4b']}
    

    【讨论】:

    • 当然,请注意不要在任何数据中使用逗号或分号。
    【解决方案4】:

    显然,您不能从原始文本输出中删除 \n 和 \t,但是您可能可以在其中添加/包含更多字符,这样

    Key 1     
      Value 1   
    Key 2     
      Value 2 
    Key 3  
      Value 3a  
      Value 3b
    

    看起来像这样

    "Key 1":[      
      Value 1   
    ],   
    "Key 2":[     
      Value 2  
    ],  
    "Key 3":[
      Value 3a,  
      Value 3b
    ]    
    

    那么就可以通过下面的方式使用json解析器了

    import json    
    myDict = json.loads(my_str)  
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-05-19
      • 2013-03-13
      • 2017-03-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多