2017-12-11 13 views
1

テキストファイルを入力する必要があるプログラムがあり、それぞれのコード行でいくつかのことを行います。Python - テキストファイルからの文字列の確認形式

私はテキストファイルで何かできるようになる前に、すべての行が特定の形式に一致するようにする必要があります。この場合、都市名(任意の文字列でも構いません。実際の都市名)、続いて数字の後に '、'が続きます。

典型的な行は次のようになります。

towna、

この2.43は私が現時点で持っているもので、それはプログラムを機能させるという点で動作しますが、それはしていませんデータが正しいことを確認してください。間違っていると(時には間に合うかもしれませんが)、私にエラーが発生します。私はre.matchについていくつかのことを読んでいますが、私はそれを使う方法を理解していません。

def read_file(fileName): 
    weatherFile = open(fileName) 
    for line in weatherFile: 
     stripped = line.replace(' ','') 
     pass #add data validation for file 
     town, rain = stripped.split(",") 
     if checkIfExists(town): 
      dataList.append({"city":town, "average_rainfall":float(rain.rstrip())}) 
     else: 
      print("It looks like {0} is on the list twice. Please ensure all towns in {1} only appear once and try again." .format(town, fileName)) 
      break 

答えて

1

私が答えを出す前に、検証が始まる前にデータが煩わしいことを指摘しておきます。

ユーザーがSaint Jose,23.0と入力した場合はどうなりますか?コード内のこの行stripped = line.replace(' ','')は、SaintJose,23.0に置き換えられます。

これを解決するには、単純であり、正規表現のビットで行うことができます。

あなたはジェネレータ式とそれをさらに短くすることができます
import re #python regex 

def read_file(fileName): 
    pattern = re.compile(r'(.*?),([-+]?(?:\d+\.\d*|\.?\d+)(?:[eE][-+]?\d+)?)') 
    with open(fileName) as weatherFile: 
     for line in weatherFile: 
      if not pattern.fullmatch(line.strip()): 
       continue 
      town, rain = line.split(",") 
      if checkIfExists(town): 
       dataList.append({"city":town, "average_rainfall":float(rain.rstrip())}) 
      else: 
       print("It looks like {0} is on the list twice. Please ensure all towns in {1} only appear once and try again." .format(town, fileName)) 
       break 

def read_file(fileName): 
    pattern = re.compile(r'(.*?),([-+]?(?:\d+\.\d*|\.?\d+)(?:[eE][-+]?\d+)?)') 
    with open(fileName) as weatherFile: 
     for town, rain in (line.split(",") for line in weatherFile if pattern.fullmatch(line.strip())) 
      if checkIfExists(town): 
       dataList.append({"city":town, "average_rainfall":float(rain.rstrip())}) 
      else: 
       print("It looks like {0} is on the list twice. Please ensure all towns in {1} only appear once and try again." .format(town, fileName)) 
       break 

このライン:

pattern = re.compile(r'(.*?),([-+]?(?:\d+\.\d*|\.?\d+)(?:[eE][-+]?\d+)?)') 

は再利用のための正規表現をコンパイルします。これはしばしば、複雑な正規表現の方が効率的であるため、正規表現エンジンはマッチングのために正規表現が使用されるたびに正規表現エンジンが内部状態を再評価して再構築する必要がありません。

ずにマッチングするための同等の事前コンパイルする正規表現は、次のようになります。

re.fullmatch(your_string_expression, r'(.*?),([-+]?(?:\d+\.\d*|\.?\d+)(?:[eE][-+]?\d+)?)') 

あなたは(これは1 ([-+]?(?:\d+\.\d*|\.?\d+)(?:[eE][-+]?\d+)?))int型または浮動小数点数を一致させるために使用され、それが理由です見怖い探しの正規表現すごく長い。 Pythonにはhereが定義されています。私がここで使用したのは、一致するintと浮動小数点を組み合わせたもので、使用例はhereです。

+0

ありがとう、パターン= re.compile行の意味を簡単に説明できますか? – Mick

+0

@Mick、説明を追加しました – smac89

0

一部の人々は、問題に直面したとき、「私が知っている、私は正規表現を使用します。」と思います今、彼らには2つの問題があります。私は許すCSVファイルとしてファイルを扱います

validators = { 
    'City Name': [ 
     UniqueValidator() 
    ], 
    'Average Rainfall': [ 
     FloatValidator() 
    ] 
} 

Regular Expressions: Now You Have Two Problems


:(ジェイミー・ザウィンスキーは)

は、以下の提案次の検証定義に(.*?),([-+]?(?:\d+\.\d*|\.?\d+)(?:[eE][-+]?\d+)?)正規表現を比較しますcsv moduleを使用してそれを読み取り、vladiateのようなCSVスキーマ検証パッケージを使用してください。この問題にサードパーティーを使用する必要はありませんが、懸案事項を分かち合い、優れた検証ロジック定義を可能にします。私たちはどう定義するかに注意してください(次のコードを実行し、

City Name,Average Rainfall 
towna,2.43 
townb,1.01 
townc,invalid_value 

をそして:あなたは次の内容のcities.csvファイルを持っているかどう

例えば、(「平均降雨量」欄のinvalid_valueに注意してください)ユニークな「都市名」値の要件と「平均降雨量」のfloat値のバリデータ):あなたが印刷され見ることが

import csv 

from vladiate import Vlad 
from vladiate.validators import UniqueValidator, FloatValidator 
from vladiate.inputs import LocalFile 


class CityValidator(Vlad): 
    validators = { 
     'City Name': [ 
      UniqueValidator() 
     ], 
     'Average Rainfall': [ 
      FloatValidator() 
     ] 
    } 


def read_file(file_name): 
    CityValidator(source=LocalFile(file_name)).validate() 

    with open(file_name) as weather_file: 
     reader = csv.reader(weather_file) 
     for city_name, average_rainfall in reader: 
      print(city_name, average_rainfall) 


read_file("cities.csv") 

City Name Average Rainfall 
towna 2.43 
townb 1.01 
townc invalid_value 

Validating CityValidator(source=LocalFile('cities.csv')) 
Failed :(
    FloatValidator failed 1 time(s) (33.3%) on field: 'Average Rainfall' 
    Invalid fields: ['invalid_value'] 
+0

申し訳ありませんが、これはテストの一部なので、テキストファイルから読み込む必要があります。 – Mick

+0

@Mick問題ではない、あなたはまだアイデアを使用することができます。たとえば、 'from vladiate.inputs import String'は、ファイルではなく文字列を検証することができます。 – alecxe

関連する問題