【问题标题】:Python - Check Order of Lines in FilePython - 检查文件中的行顺序
【发布时间】:2009-12-19 03:01:22
【问题描述】:

如何检查文件中的行顺序?

示例文件:

a b c d e f
b c d e f g
1 2 3 4 5 0

要求:

  1. 所有以 a 开头的行,必须在以 b 开头的行之前。
  2. a 开头的行数没有限制。
  3. 以 a 开头的行可能存在也可能不存在。
  4. 包含整数的行,必须遵循以 b 开头的行。
  5. 数字行必须至少有两个整数,后跟零。
  6. 不满足条件必须引发错误。

我最初认为 for 循环相当冗长,但失败了,因为我无法索引 line[0] 之外的行。另外,我不知道如何定义一条线相对于其他线的位置。这些文件的长度没有限制,因此内存也可能是个问题。

非常欢迎任何建议!欢迎这个迷茫的新手简单易读!

谢谢, 海鲜。

【问题讨论】:

  • 有人问我是人类还是脚本!非常有趣!剧本有条不紊,我是一个混乱的狂热者,我的剧本也是如此!我喜欢这个网站!
  • 您是在寻找执行此操作的代码还是一般策略?我最初对这个问题的解决方案的想法会导致生成相当多的代码......我不认为它可以在几行中完成......

标签: python file lines


【解决方案1】:

一种简单的迭代方法。这定义了一个函数来确定从 1 到 3 的线型。然后我们遍历文件中的行。未知的线型或小于任何先前线型的线型将引发异常。

def linetype(line):
    if line.startswith("a"):
        return 1
    if line.startswith("b"):
        return 2
    try:
        parts = [int(x) for x in line.split()]
        if len(parts) >=3 and parts[-1] == 0:
            return 3
    except:
        pass
    raise Exception("Unknown Line Type")

maxtype = 0

for line in open("filename","r"):  #iterate over each line in the file
    line = line.strip() # strip any whitespace
    if line == "":      # if we're left with a blank line
        continue        # continue to the next iteration

    lt = linetype(line) # get the line type of the line
                        # or raise an exception if unknown type
    if lt >= maxtype:   # as long as our type is increasing
        maxtype = lt    # note the current type
    else:               # otherwise line type decreased
        raise Exception("Out of Order")  # so raise exception

print "Validates"  # if we made it here, we validated

【讨论】:

  • @Mark - 我遵循您定义函数的部分,但是,for 循环使我无法理解。你介意稍微注释一下吗?
【解决方案2】:

您可以使用lines = open(thefile).readlines() 将所有行放入一个列表中,然后根据您的需要处理该列表——不是最高效,而是最简单。

同样最简单的方法是执行多个循环,每个条件一个(除了 2,它不是可以违反的条件,而 5 不是真正的条件;-)。 “所有以a开头的行,必须在以b开头的行之前”可以被认为是“以a开头的最后一行,如果有的话,必须在以b开头的第一行之前”,所以:

lastwitha = max((i for i, line in enumerate(lines)
                 if line.startswith('a')), -1)
firstwithb = next((i for i, line in enumerate(lines) 
                   if line.startswith('b')), len(lines))
if lastwitha > firstwithb: raise Error

然后对于“包含整数的行”类似:

firstwithint = next((i for i, line in enumerate(lines)
                     if any(c in line for c in '0123456789')), len(lines))
if firstwithint < firstwithb: raise Error

这对你的作业真的应该有很多提示——你现在可以自己做最后剩下的一点吗,条件 4?

当然,您可以采取与我在这里的建议不同的策略(使用next 来获取满足条件的行的第一个数字——这需要Python 2.6,顺便说一句——以及any 和@987654326 @ 来满足序列中的任何/所有项目是否满足条件)但我正在尝试匹配您的请求以实现最大的简单性。如果您发现传统的for 循环比nextanyall 更简单,请告诉我们,我们将展示如何将这些高级抽象形式的使用重新编码为那些低层概念!

【讨论】:

  • @Alex,我明白这一点。清晰、清晰、简单!但是,“如果不是唯一参数,则必须将生成器表达式括起来”是什么意思,因为当我尝试实现代码时会引发这种情况。我会试着整理一下你留给我的条件,稍后再贴出来。
  • 另外,""所有以 a 开头的行,必须在以 b 开头的行之前" 可能被认为是"以 a 开头的最后一行,如果有的话,必须在以 b 开头的第一行之前""程序员看待问题的方式很棒!
  • @seafoid,是的,看起来我省略了括号——编辑修复。
【解决方案3】:

您不需要为这些行编制索引。对于每一行,您都可以检查/设置一些条件。如果不满足某些条件,则引发错误。例如。规则 1:您将变量 was_b 最初设置为 False。在每次迭代中(除了其他检查/集合),还要检查该行是否以“b”开头。如果是,则设置 was_b = True。另一项检查是:如果行以“a”开头并且 was_b 为真,则引发错误。另一个检查是:如果 line 包含整数并且 was_b 为 False,则引发错误.. 等等

【讨论】:

    【解决方案4】:

    线路限制:

    I。在我们遇到以'b' 开头的行之后,不得有以'a' 开头的行。

    II。如果我们遇到一个数字行,那么前一个必须以'b' 开头。 (或者您的第 4 个条件允许另一种解释:每个 'b' 行必须后跟一个数字行)。

    数字行的限制(作为正则表达式):/\d+\s+\d+\s+0\s*$/

    #!/usr/bin/env python
    import re
    
    is_numeric = lambda line: re.match(r'^\s*\d+(?:\s|\d)*$', line)
    valid_numeric = lambda line: re.search(r'(?:\d+\s+){2}0\s*$', line)
    
    def error(msg):
        raise SyntaxError('%s at %s:%s: "%s"' % (msg, filename, i+1, line))
    
    seen_b, last_is_b = False, False
    with open(filename) as f:
        for i, line in enumerate(f):
            if not seen_b:
               seen_b = line.startswith('b')
    
            if seen_b and line.startswith('a'):
               error('failed I.')
            if not last_is_b and is_numeric(line):
               error('failed II.')
            if is_numeric(line) and not valid_numeric(line):
               error('not a valid numeric line')
    
            last_is_b = line.startswith('b')
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-19
      • 2017-12-31
      • 2022-01-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多