1

ファイル内の行の順序を確認するにはどうすればよいですか?

サンプルファイル:

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. 数値行には、少なくとも2つの整数とそれに続くゼロが必要です。
  6. 条件を満たさない場合、エラーが発生する必要があります。

最初はかなり長いforループを考えていましたが、line [0]を超える行にインデックスを付けることができないため、失敗しました。また、ある線の位置を他の線と比較して定義する方法がわかりません。これらのファイルの長さに制限はないため、メモリも問題になる可能性があります。

どんな提案も大歓迎です!この混乱した初心者にとって、シンプルで読みやすいものは大歓迎です!

ありがとう、Seafoid。

4

4 に答える 4

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
于 2009-12-19T03:27:16.363 に答える
2

必要に応じて、すべての行をリストに入れ、リストでlines = open(thefile).readlines()作業することができます-最大限に効率的ではありませんが、最大限に単純です。

繰り返しますが、最も簡単な方法は、条件ごとに 1 つずつ、複数のループを実行することです (ただし、違反する可能性のある条件ではない 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 が必要です) anyall条件)しかし、私は最大限のシンプルさのためにあなたの要求に合わせようとしています. 従来のforループがnextanyおよびよりも単純であるallことがわかった場合はお知らせください。これらの高度な抽象化形式の使用を下位層の概念に再コード化する方法を示します。

于 2009-12-19T03:16:18.107 に答える
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')
于 2009-12-19T08:00:37.203 に答える
0

行にインデックスを付ける必要はありません。すべての行について、いくつかの条件をチェック/設定できます。条件が満たされない場合は、エラーを発生させます。たとえば、ルール 1: 変数 was_b を最初に False に設定します。各繰り返しで(他のチェック/セット以外に)、行が「b」で始まるかどうかもチェックします。その場合は、was_b = True に設定します。別のチェック: 行が「a」で始まり、was_b が true の場合、エラーが発生します。別のチェックは次のとおりです。行に整数が含まれていて、was_b が False の場合、エラーが発生します。など

于 2009-12-19T03:30:42.113 に答える