【问题标题】:Python: Convert Table with Missing Data and Irregular Pattern to DictionaryPython:将缺少数据和不规则模式的表转换为字典
【发布时间】:2023-03-16 16:27:01
【问题描述】:

在 Python 2.6 中,用 Python 方式过滤包含不规则宽度、缺失数据和缩进的子条目的 ASCII 表以将它们转换为字典的方法是什么?

col1      col2  col3       col4 
A         B                D          
 A1       B1    C1          
 A2       B2               

您希望输出类似于:

{"col1":"A","col2":"B","col3":"","col4":"D",
indented_entries:[
  {"col1":"A1","col2":"B1","col3":"C1","col4":""},
  {"col1":"A2","col2":"B2","col3":"","col4":""}
]}

虽然您可以遍历固定字符宽度列,但我的问题是,是否有人对实现有一个优雅的想法?


现实生活场景

我有一个包含一些列和一些不规则模式(缩进行)的 ASCII 表。数据如下:

ty      eq  status       use state  ord   capacity      free    ra  part high low
ma      10  m----3---r-   1% on          558.912G  555.888G    1M    16   80% 70%
 mm      11               1% on       0  558.912G  558.894G  [586042464 inodes]
 mr      12               1% on       1  558.912G  555.888G

我想将这些数据解析成字典,所以它看起来像这样:

{
  "ty": "ma",
  "eq": "10",
  "status": "m----3---r-",
  "use": "1%",
  "state": "on",
  "capacity": "558.912G",
  "free": "555.888G",
  "ra": "1M",
  "part": "16",
  "high": "80%",
  "low": "70%",
  "_ty": [
    {
      "ty": "mm",
      "eq": "11",
      "use": "1%",
      "state": "on",
      "ord": "0",
      "capacity": "558.912G",
      "free": "558.894G [586042464 inodes]"
    },
    {
      "ty": "m4",
      "eq": "12",
      "use": "1%",
      "state": "on",
      "ord": "1",
      "capacity": "558.912G",
      "free": "555.888G"
    }
  ]
}

我想知道在 Python (2.6) 中执行此操作的优雅方法。有什么想法吗?

也将考虑忽略“子行”并仅返回顶层的解决方案。

我的一些尝试:

def panda_conversion(filename):
        import pandas
        return pandas.read_csv(filename,sep='\s+').T.to_dict()


def convert_table_to_dict(filename):
        import csv
        return list(csv.DictReader(open(filename), delimiter=' '))


def convert_ascii_table(filename):
        import asciitable
        return asciitable.read(filename, Reader=asciitable.FixedWidth,
                col_starts=( 0, 8,  12, 25, 29, 37, 41, 51, 61, 69, 73, 78 ),
                col_ends  =( 2, 11, 23, 28, 34, 40, 50, 60, 68, 71, 76, 81 ))

if __name__ == '__main__':
        import sys
        import json
        filename = sys.argv[1:][0]
        print( panda_conversion( filename ) )
        print( json.dumps( convert_table_to_dict( filename ), indent=1))
        print( convert_ascii_table( filename ) )

顺便说一句,根据 cmets 我没有正确执行此操作,您不需要发布代码。只要有想法就足够了。谢谢。

【问题讨论】:

  • 请按照您创建此帐户时的建议阅读并遵循帮助文档中的发布指南。 On topichow to ask 在这里申请。 StackOverflow 不是设计、编码、研究或教程服务。
  • 弄清楚如何解析不同类型的行;编写解析函数;遍历每一行并决定使用哪个函数来解析它;解析后,酌情将其添加到您的容器中。
  • 谢谢,@Prune。还没有找到我的问题不符合要求的地方。我不经常做 StackOverflow,所以为尴尬而道歉。我知道该怎么做,我可以迭代每一行并解析它,确定每列(开始和结束)字符的宽度。我只是认为这是一种不好的方法,并想与过去可能遇到过类似问题的其他人讨论。
  • @gtamorim:您没有尝试自己解决问题。整个问题超出了 SO 的范围。
  • 我做到了。只是对此不满意。最后一个是使用 asciitable(现已停产,但 astropy 已取代它)。

标签: python ascii python-2.6


【解决方案1】:

这可行,但它非常不符合 Python 风格。

def iterate(filename):
        d={}
        f = open(filename,'r')
        header = f.readline().split()
        header_parent = list(header)
        header_parent.remove("ord")
        header_child = [e for e in header if e not in ("status","part","high","low" )]

        for line in f:
                if not line[0] == ' ':
                        for columns in header_parent:
                                d[columns] = line.split()[header_parent.index(columns)]
                else:
                        for columns in header_child:
                                d["_"+columns] = '' if (header_child.index(columns) >= len(line.split()) ) else line.split()[header_child.index(columns)]

        return d

你知道如何改进吗?

【讨论】:

  • 该答案(连同您的问题的编辑版本)非常适合 codereview.se
  • 感谢@DavidPostill。我会这样做的。
猜你喜欢
  • 1970-01-01
  • 2022-12-05
  • 2012-09-18
  • 1970-01-01
  • 2018-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多