0

関数の特定の入力ファイルのルールのリストがあります。指定されたファイルでそれらのいずれかに違反している場合、プログラムにエラーメッセージを返して終了させたい.

  • 最初の行は「#」記号 (ヘッダー行を示す) で開始する必要があります。
  • 各行には正確に 10 列が必要です
  • 列 2 (0 から数えて) は + または - 記号のいずれかである必要があります
  • 列 8 は整数のカンマ区切りのリストである必要があります
  • 列 9 は、列 8 とまったく同じ数の整数を持つ、コンマ区切りの整数のリストである必要があります。

これを行うために、次のコードを作成しました。

スティーブの回答をコードに編集

with open(infile, 'r') as fp:
line = fp.readline().strip()
if not line.startswith('#'):
    print ('First line does not start with #')
    sys.exit(1)
n = 1
for line in fp.readlines():
    d = '(\d+,\d+)'
    n += 1
    cols = line.strip().split()
    i = search(d, line)
    if len(cols) != 10:
        print('Lenth not equal to 10')
        sys.exit(1)
    if cols[2] != '+' or '-':
        print('Column 2 is not a + or - symbol')
        sys.exit(1)
    if i and cols[8] != i.group(1):
        print('Column 8 is not a comma-separated list of integers')
        sys.exit(1)
    if i and cols[9] != i.group(1) and len(cols[9]) != len(cols[8]):
        print('Column 9 in not a comma-separated list of integers with the exact same number of integers in column 8')
        sys.exit(1)

しかし、これを実行すると、すべての条件が機能しているようには見えません。私はこれを正しくやろうとしていますか?

4

1 に答える 1

3

この行は間違っています:

if cols[2] != '+' or '-':

これは正しいでしょう:

if not (cols[2] == '+' or cols[2] =='-'):

代わりにこれをお勧めします:

if cols[2] not in ('+', '-'):

また、電話しないことをお勧めしますfp.readlines()。ファイル オブジェクトfpは反復子として機能し、反復すると一度に 1 行ずつ取得されます。したがって、ループは次のようになります。

for line in fp:

nまた、行番号を追跡しているように見えますか?その場合、次のような慣用的な Python の方法があります。

for n, line in enumerate(fp, 1):

enumerate()イテレータを取り、イテレータから次の値を増分カウントとともに返します。デフォルトでは、カウントは 0 から始まりますが、オプションで開始番号を指定できます。ここでは 1 から開始するようにしました。

Python では、このwithステートメントを使用してファイルを開くのがベスト プラクティスであるため、次のようにすることをお勧めします。

with open(infile, 'r') as fp:
    line = fp.readline().strip()
    if not line.startswith('#'):
        print ('First line does not start with #')
        sys.exit(1)
    for line in fp:
        # process lines here

あなたが示しているコードは、私には完全には意味がありません。この行:

i = search(d, line)

すでにコマンドを実行している必要がありますfrom re import search。実際には、実行してimport reから明示的に呼び出すことをお勧めre.search()しますが、それは好みの問題だと思います。とにかく、これiは一致グループの結果に設定されますre.search()(またはNone一致が失敗した場合はに)。しかし、後でrではなくテストしているコードでi、ここに表示されているコードを決して設定rしないため、それが何をするかわかりません。個人的にはm、一致グループの変数名として使用します。

正規表現は、正の整数のペアと一致します。整数の数は数えません。 len(cols[8])の文字数をチェックしていcols[8]ます。

文字列メソッド function を呼び出していますが.split('')、これは正しくありません。私のシステムでは、例外が発生します。空白で分割するValueError: empty separator だけです。.split()コンマで区切られた整数リストには空白があってはならないと仮定します。

最後に、PEP 8 のガイドラインを考慮してください。変数FirstLineは、変数名ではなくクラス名のように大文字になっています。それは私を正確に混乱させるわけではありませんでしたが、気を散らすものでした. Python コミュニティのほとんどは PEP 8 に従っています。

http://www.python.org/dev/peps/pep-0008/

上記のすべてを考慮して、コードを書き直しました。

import sys

def parse_list_of_int(s):
    try:
        return [int(x) for x in s.split(',')]
    except Exception:
        return None

with open("test.txt", 'r') as f:
    # read line 1
    line = f.readline().strip()
    if not line.startswith('#'):
        print ('First line does not start with #')
        sys.exit(1)

    # need to start enumerate() at 2 because we pulled line 1 out above
    for i, line in enumerate(f, 2):
        cols = line.strip().split()
        if len(cols) != 10:
            print('line {0}: Length not equal to 10'.format(i))
            sys.exit(1)
        if cols[2] not in ('+', '-'):
            print('line {0}: Column 2 is not a + or - symbol'.format(i))
            sys.exit(1)
        lst8 = parse_list_of_int(cols[8])
        if lst8 is None:
            print('line {0}: Column 8 is not a comma-separated list of integers').format(i)
            sys.exit(1)
        lst9 = parse_list_of_int(cols[9])
        if lst9 is None:
            print('line {0}: Column 9 is not a comma-separated list of integers'.format(i))
            sys.exit(1)
        if len(lst8) != len(lst9):
            print('line {0}: Column 8 and column 9 do not have same number of integers'.format(i))
            sys.exit(1)

print('No problems!')
sys.exit(0)

整数のリストを解析し、Python リストを作成して返す単純な関数を作成しました。その後、コードは 2 つのリストが同じ長さであるかどうかを実際に適切にチェックできます。

于 2012-04-24T20:45:58.433 に答える