如何检查文件中的行顺序?
示例文件:
a b c d e f
b c d e f g
1 2 3 4 5 0
要求:
我最初认为是一个相当冗长的for循环,但由于我无法索引超出行[0]的行,因此失败了。另外,我不知道如何定义一行相对于其他行的位置。这些文件的长度没有限制,因此内存也可能是一个问题。
任何建议都非常欢迎!这个迷茫的新手欢迎简单易读!
谢谢, Seafoid。
答案 0 :(得分:4)
一种简单的迭代方法。这定义了一个函数来确定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
答案 1 :(得分: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
这个shouild真的很适合你的作业 - 你现在可以自己做最后一点,条件4吗?
当然你可以从我在这里提出的建议中采取不同的方法(使用next
来获得满足条件的第一个数字 - 这需要Python 2.6,btw - 和{{1} }和any
以满足序列中的任何/所有项目是否满足条件)但我正在尝试匹配您的请求以获得最大程度的简单性。如果您发现传统的all
循环比for
,next
和any
更简单,请告诉我们,我们将展示如何将更高抽象形式的这些用途重新编码为低层概念!
答案 2 :(得分:0)
您无需为线索引。对于每一行,您可以chceck /设置一些条件。如果不满足某些条件,则引发错误。例如。规则1:您将变量was_b初始设置为False。在每次迭代中(除了其他检查/集合之外),还要检查行是否以“b”开头。如果是,请设置was_b = True。另一个检查是:如果行以“a”开头且was_b为真,则引发错误。另一个检查是:如果line包含整数而was_b为False,则引发错误.. etc
答案 3 :(得分:0)
对行的限制:
I
。在我们遇到以'a'
开头的行后,必须没有以'b'
开头的行。
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')