【问题标题】:Splitting lines of a text file into part of a tuple-Python将文本文件的行拆分为元组 Python 的一部分
【发布时间】:2012-04-09 05:42:31
【问题描述】:

我正在开发一个汇编程序并选择使用 Python 而不是 C(主要是因为 Python 可以处理列表,我想学习它)

我的问题是如何将文本文件的每一行拆分为元组的一部分?

例如测试文件是:

ADD R1,R2;  
OR R1,R3;

并有代码将其解析成这个

UserProgram=[['ADD','R1','R2'],['OR','R1','R3']]

它还必须忽略分号后的 cmets。谢谢!

【问题讨论】:

  • 来自 C 背景,Python 似乎有点奇怪。可以预见的是,我尝试使用 for 循环来拆分列表的每个元素(单行)。我还尝试了多个分隔符拆分,但也无法运行。在此之前我必须做的程序是一个 5 阶段的流水线架构模拟器。希望我更了解 Python,因为它看起来会更好。

标签: python split tuples


【解决方案1】:
>>> s = "ADD R1,R2; OR R1,R3;"
>>> t1 = s.split(';')
>>> t1
['ADD R1,R2', ' OR R1,R3', '']
>>> UserProgram = [t.strip().replace(',', ' ').split(' ') for t in t1 if len(t) > 0]
>>> UserProgram
[['ADD', 'R1', 'R2'], ['OR', 'R1', 'R3']]
>>> 

顺便说一下,方括号表示列表,而不是元组。

【讨论】:

  • 啊,是的!谢谢@Li-aungYip。
  • -1 这遗漏了额外的要求(它们可能在以后被编辑过?)并且对于像这样的简单情况,手动构建列表很笨拙。应该强烈鼓励 IMO 开始使用 Python 的 C 程序员摆脱他们在直接迭代方面的思维习惯。
  • @KarlKnechtel,嗨,我已经编辑它以使用快捷方式列表创建。
【解决方案2】:

如果您的来源是这种格式

source="""
ADD R1,R2;
OR R1,R3;
"""

然后您可以简单地通过 splitlines() 线性拆分源,然后使用 ; 作为分隔符再次拆分,丢弃 ';' 之后的任何内容

sourcelines=[x.split(";")[0].replace(',',' ').split() 
             for x in source.splitlines() if x]
[['ADD', 'R1', 'R2'], ['OR', 'R1', 'R3']]

您还可以继续前进并将每个 ASM 源代码行拆分为 OP-Code 和单独的操作数。

[[token.split(',') for token in x.split(";")[0].split()] 
  for x in source.splitlines() if x]

你会得到类似的东西

[[['ADD'], ['R1', 'R2']], [['OR'], ['R1', 'R3']]]

【讨论】:

    【解决方案3】:

    所以我们有一个该格式的源文件。

    我们想要文件中每一行的标记列表。

    这些标记是在第一个分号之后删除所有内容并将其余部分拆分为逗号或空格的结果。我们可以通过用空格替换逗号来做到这一点,然后只用空格分割。

    所以我们转向标准库。字符串的split 方法在您不给它拆分时会在空格上拆分。 replace 方法允许我们用另一个子字符串替换一个子字符串(例如,','' ')。要删除分号后的所有内容,我们可以partition 并获取第一部分(结果的元素 0)。* 单独一行的处理看起来像

    line.partition(';')[0].replace(',', ' ').split()
    

    然后我们只需对文件的每一行执行此操作。要获得将某些函数应用于源元素的结果列表,我们可以使用列表推导直接请求它(基本上我们描述了结果列表应该是什么样子)。 Python 中的文件对象是行的有效来源;您可以对其进行迭代(这个概念可能对 C++ 程序员来说更熟悉)并且元素是文件的行。

    所以我们需要做的就是打开文件(我们习惯性地使用with 块来管理文件)并生成列表:

    with open('asm.s') as source:
        parsed = [
            line.partition(';')[0].replace(',', ' ').split()
            for line in source
        ]
    

    完成。

    * 或再次使用split,但我发现这不太清楚,因为生成元素列表实际上不是您的目标。

    【讨论】:

      【解决方案4】:
      >>> import re
      >>> [re.split('\W+', s.strip()) for s in 'ADD R1,R2; OR R1,R3;'.split(';') if s]
      [['ADD', 'R1', 'R2'], ['OR', 'R1', 'R3']]
      

      UPD:

      python -m timeit -s "import re; regexp = re.compile('\W+');" "[regexp.split(s.strip()) for s in 'ADD R1,R2; OR R1,R3;'.split(';') if s]"
      100000 loops, best of 3: 3.34 usec per loop
      
      python -m timeit "[t.strip().replace(',', ' ').split(' ') for t in 'ADD R1,R2; OR R1,R3;'.split(';') if t]"100000 loops, best of 3: 2.1 usec per loop
      

      顺便说一句,我的变种还不错,虽然有点慢

      【讨论】:

      • 你为什么要使用re.split 来获得str.split 的默认行为而不带参数?这也不需要你先strip() 字符串。
      • 不,string.split 只会分割空格,而不是逗号。你们都在拆分之前做replace(',', ' '),但我建议使用正则表达式进行另一种实现
      【解决方案5】:
      >>>s = "ADD R1,R2; OR R1,R3;"
      >>>[substr.split() for substr in s.replace(',',' ').split(';')[:-1]]
      [['ADD', 'R1', 'R2'], ['OR', 'R1', 'R3']]
      

      【讨论】:

      • 汇编注释从行的第一个分号开始,而不是最后一个;你应该在这里使用[0] 而不是[:-1]
      • 当您在; 上拆分时,第一个分号之前的所有内容都是您真正想要的。在您的示例字符串中,OR R1,R3; 实际上是一个注释,因为它出现在; 之后。 ; == '#' 在 Python 中,所以你需要一个换行符。
      猜你喜欢
      • 1970-01-01
      • 2014-10-03
      • 1970-01-01
      • 2014-06-28
      • 2012-11-29
      • 2014-03-28
      • 1970-01-01
      • 2017-02-08
      • 1970-01-01
      相关资源
      最近更新 更多