【问题标题】:Fast wayq to convert list of dot-separated strings to YAML?将点分隔字符串列表转换为 YAML 的快速方式?
【发布时间】:2021-10-25 17:33:08
【问题描述】:

假设我有一个这样的字符串列表:

strings = ["foo.bar.1", "foo.bar.2", "foo.bar.A.1", "foo.bar.A.2"]

我想创建一个这样的 YAML 输出:

foo:
  - bar:
     - 1
     - 2
     - A:
         - 1
         - 2

Python 字典似乎很好地映射到任务,所以我尝试了类似这样的方法,它接受一个点分隔的字符串并返回一个嵌套字典:

def dot_string_to_dictionary(dot_string):
  dictionary = {}
  split_string = dot_string.split(".")
  current_dictionary = dictionary
  for part in split_string:
    current_dictionary[part] = {}
    current_dictionary = current_dictionary[part]
  return dictionary
  

我正在考虑每个字符串,我可以通过这个函数运行它来获取字典。然后,我可以用这个新字典更新一些全局/主字典。最后,我可以将主字典写入 YAML。

【问题讨论】:

  • 这是您想要的确切 YAML,还是类似的东西?您的函数不会生成相应的数据结构,即{'foo': [{'bar': [1, 2, {'A': [1, 2]}]}]}

标签: python json python-3.x dictionary yaml


【解决方案1】:

只是为了好玩,我制作了解析器。

想法是转换字符串

foo.bar.1
foo.bar.2
foo.bar.A.1
foo.bar.A.2
too.bar.1
too.bar.2
too.bar.A.1
too.bar.A.2

进入表格:

foo bar 1
foo bar 2
foo bar A 1
foo bar A 2
too bar 1
too bar 2
too bar A 1
too bar A 2

从重复值中清除列并在非空单元格之间添加:

foo: bar: 1
2
A: 1
2
too: bar: 1
2
A: 1
2

并将表格折叠到 yaml 文本中:

foo:
  bar:
    1
    2
    A:
      1
      2
too:
  bar:
    1
    2
    A:
      1
      2

代码如下:

import re

strings = [
    "foo.bar.1", "foo.bar.2", "foo.bar.A.1", "foo.bar.A.2",
    "too.bar.1", "too.bar.2", "too.bar.A.1", "too.bar.A.2",
]

# make the table, and reverse it
table = list(reversed(sorted([s.split(".") for s in strings])))

# clean columns of the table
for i,row in enumerate(table[:-1]):
    if table[i+1][0] == row[0]: row[0] = ""
    for c,cell in enumerate(row[:-1]):
        if table[i+1][c] == cell and table[i][c-1] == "": table[i][c] = ""

# add ":" between non-empty cells
for i,row in enumerate(table):
    for c,cell in enumerate(row[:-1]):
        if cell != "": table[i][c] += ":"

# add two spaces into cells
for i,row in enumerate(table):
    for c,cell in enumerate(row):
        table[i][c] = "  " * c + table[i][c]

# reverse table
table = list(reversed(table))

# convert table into yaml
yaml = "\n".join(["\n".join(row) for row in table])
yaml = re.sub(r"\s*\n\s*\n", "\n", yaml, re.MULTILINE) # remove empty lines

print(yaml)

【讨论】:

    【解决方案2】:

    另一种解决方案。嗯,它更短。它完成了这项工作。但我不敢评论(反正没人关心):

    strings = [
        "foo.bar.1", "foo.bar.2", "foo.bar.A.1", "foo.bar.A.2",
        "too.bar.1", "too.bar.2", "too.bar.A.1", "too.bar.A.2" ]
    
    strings = list(reversed(sorted(strings)))
    
    for i,s in enumerate(strings[:-1]):
        for c,ch in enumerate(s):
            if ch != strings[i+1][c]: break
        strings[i] = "." * (len(s[:c].split("."))-1) + s[c:]
    
    for i,s in enumerate(strings):
        strings[i] = ":\n".join(["  "*n+c for n,c in enumerate(s.split(".")) if c])
    
    yaml = "\n".join(reversed(strings))
    
    print(yaml)
    

    输出:

    foo:
      bar:
        1
        2
        A:
          1
          2
    too:
      bar:
        1
        2
        A:
          1
          2
    

    【讨论】:

      【解决方案3】:

      您似乎正在寻找“yaml.dump”。 参考:http://pyyaml.org/wiki/PyYAMLDocumentation

      这是来自参考文档的示例:

      import yaml
      document = """
        a: 1
        b:
         c: 3
         d: 4
      """
      print yaml.dump(yaml.load(document))
      give
      
      a: 1
      b: {c: 3, d: 4}
      

      完全披露:我有很多使用 Ansible 的 YAML 经验,但我以前从未使用过这个特殊功能。我做了一些研究,发现使用 yaml.dump 工具可以解决类似的问题希望它有效,这是我会尝试的。

      【讨论】:

        猜你喜欢
        • 2010-10-19
        • 1970-01-01
        • 2020-04-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-03
        • 1970-01-01
        • 2016-01-31
        相关资源
        最近更新 更多