【问题标题】:Read list written in different ways from file从文件中读取以不同方式写入的列表
【发布时间】:2014-12-10 13:47:20
【问题描述】:

我需要一种方法来以几种不同的方式读取存储在文件中的列表。我正在尝试考虑用户可能会想到将列表存储在文件中的所有方式,并正确地解释它。

这是一个示例输入文件,其中列表的写法不同。

# in_file.dat

# List 1 (enclosing brackets, comma separated, spaces after commas)
[0.5, 0.2, 0.6, 0.9, 1.5]

# List 2 (enclosing parenthesis, comma separated, no spaces or some spaces after commas)
(0.5,0.2,0.6,0.9, 1.5)

# List 3 (enclosing keys, mixed commas and semi-colons, mixed no-spaces and spaces)
{0.5,0.2,0.6;0.9;1.5}

# List 4 (single item)
[0.6]

# List 5 (space separated elements)
[2.3 5. 0.6 1.2 0.0 3.1]

每一行都应该被正确读取为一个列表,结果是:

ls_1 = [0.5, 0.2, 0.6, 0.9, 1.5]
ls_2 = [0.5, 0.2, 0.6, 0.9, 1.5]
ls_3 = [0.5, 0.2, 0.6, 0.9, 1.5]
ls_4 = [0.6]
ls_5 = [2.3, 5., 0.6, 1.2, 0.0, 3.1]

我读取文件的常用方法是使用

# Read data from file.
with open('in_file.dat', "r") as f_dat:
    # Iterate through each line in the file.
    for line in f_dat:
        # Skip comments
        if not line.startswith("#") and line.strip() != '':
            # Read list stored in line.
            ls_X = ??

是否有一些通用的方法可以强制 python 将该行解释为列表?

【问题讨论】:

  • 你不想要ls_1ls_2 ... ls_6。请改用字典。
  • @Matthias 我看不出字典如何解决我的问题。你愿意扩展吗?
  • 在大多数情况下,您必须对用户将如何输入数据做出一些假设,很难制定一般规则。话虽如此,对于您的问题,我会将所有非数字和非十进制字符转换为空格并在行上执行 .split()。
  • @Gabriel:字典不会帮你解析(这就是我写comment而不是answer的原因)。我的评论是关于在运行时发明新的变量名,这是一个非常糟糕的主意。

标签: python list file io user-input


【解决方案1】:

如果您确定每一行只有数字序列,请使用 re

import re
lines=[]
for l in f_dat:
    if l and l[0]!='#':
        lines.append([float(i) for i in re.findall('[0-9.]+',l)])
print lines

希望这就是你要找的。​​p>

【讨论】:

  • 所有好的答案。我选择这个是因为它很简单而且效果很好。谢谢!
【解决方案2】:

试试这个:

import re
with open('in_file.dat', "r") as f_dat:
    for line in f_dat:
      if not line.startswith("#") and line.strip() != '':
          parts = re.split('[, ;]', line[1:-1])  # removes first and last char
          ls_X = filter(lambda x: x!="", parts)  # removes any empty string 

【讨论】:

    【解决方案3】:
    >>> file
    '[0.5, 0.2, 0.6, 0.9, 1.5]\n(0.5,0.2,0.6,0.9, 1.5)\n{0.5,0.2,0.6;0.9;1.5}\n[0.6]\n[2.3 5. 0.6 1.2 0.0 3.1]'
    >>> for line in file.split('\n'):
    ...     print re.split(r"[,\s;]\s*",re.sub(r"[{}()\[\]]",'',line))
    ... 
    ['0.5', '0.2', '0.6', '0.9', '1.5']
    ['0.5', '0.2', '0.6', '0.9', '1.5']
    ['0.5', '0.2', '0.6', '0.9', '1.5']
    ['0.6']
    ['2.3', '5.', '0.6', '1.2', '0.0', '3.1']
    

    【讨论】:

      【解决方案4】:

      也许是这样的。这也适用于嵌套结构:

      from ast import literal_eval
      import re
      from string import maketrans
      
      table = maketrans(';,{}()', '  [][]')
      with open('file.txt', "r") as f_dat:
          for line in f_dat:
              if not line.startswith("#") and line.strip() != '':
                  line = re.sub(r'\s+', ',', line.strip().translate(table))
                  try:
                      print literal_eval(line)
                  except (ValueError, SyntaxError):
                      pass
      

      演示:

      >>> !cat file.txt
      # in_file.dat
      
      # List 1 (enclosing brackets, comma separated, spaces after commas)
      [0.5,    0.2, 0.6,              [0.9, 1.5]]
      
      # List 2 (enclosing parenthesis, comma separated, no spaces or some spaces after commas)
      (0.5,0.2,0.6,0.9, 1.5)
      
      # List 3 (enclosing keys, mixed commas and semi-colons, mixed no-spaces and spaces)
      {0.5,0.2,0.6;0.9;1.5;{1, [2, 3; 100 200]}}
      
      # List 4 (single item)
      [0.6]
      
      # List 5 (space separated elements)
      [2.3 5. 0.6 1.2 0.0 3.1 [10 20 {50, [60]}] ]
      
      >>> %run so.py
      [0.5, 0.2, 0.6, [0.9, 1.5]]
      [0.5, 0.2, 0.6, 0.9, 1.5]
      [0.5, 0.2, 0.6, 0.9, 1.5, [1, [2, 3, 100, 200]]]
      [0.6]
      [2.3, 5.0, 0.6, 1.2, 0.0, 3.1, [10, 20, [50, [60]]]]
      

      【讨论】:

        猜你喜欢
        • 2013-06-17
        • 1970-01-01
        • 2015-09-03
        • 2010-12-15
        • 1970-01-01
        • 2012-05-03
        • 2016-07-12
        • 2020-02-28
        相关资源
        最近更新 更多