これを実行する方法はたくさんあります。個人的には、正規表現を使用することは避けたいと思いますが、これはおそらく効率的ではなく、表現が面倒で柔軟性に欠けるからです。ここに私が思い付いたものです:
class Entry:
def __init__(self):
self.time = None
self.animal = None
self.bird = None
self.fish = None
def __repr__(self):
fmt = "{0} {1} {2} {3}".format(
"Time: {time: <{width}}",
"Animal: {animal: <{width}}",
"Bird: {bird: <{width}}",
"Fish: {fish: <{width}}")
return fmt.format(
time=self.time, animal=self.animal,
bird=self.bird, fish=self.fish,
width=12)
def __radd__(self, other):
return self.__add__(other)
def __add__(self, other):
if type(other) == dict:
for i in [self.animal, self.bird, self.fish]:
if i in other: other[i] += 1
else: other[i] = 1
return other
elif type(other) == Entry:
return self.__add__({}) + other
else:
return self.__add__({})
def parse_log(path):
def extract(line):
start = line.find(':') + 1
return line[start:].strip()
entries = []
entry = None
with open(path, 'r') as f:
for line in f.readlines():
if line.startswith('-----'):
if entry: entries.append(entry)
entry = Entry()
elif line.startswith('Time'):
entry.time = extract(line)
elif line.startswith('Animal'):
entry.animal = extract(line)
elif line.startswith('Bird'):
entry.bird = extract(line)
elif line.startswith('Fish'):
entry.fish = extract(line)
if entry: entries.append(entry)
return entries
def print_output_1(entries):
for entry in entries:
print entry
def print_output_2(entries, time):
animals = sum([e for e in entries if e.time == time])
print "Time: {0}".format(time)
print "Name: Count:"
for animal, count in animals.items():
print "{animal: <{width}} {count}".format(
animal=animal, count=count, width=12)
logPath = 'log.log'
time = '2016-07-12 09:15:00'
entries = parse_log(logPath)
print_output_1(entries)
print ""
print_output_2(entries, time)
出力(log.log
あなたが与えた入力と一致していることを与えられた)は、次のとおりです。
Time: 2016-07-12 09:00:00 Animal: Brown Bear Bird: White Owl Fish: Salmon
Time: 2016-07-12 09:00:00 Animal: Brown Bear Bird: Parrot Fish: Tuna
Time: 2016-07-12 09:00:00 Animal: Lion Bird: White Owl Fish: Sword Fish
Time: 2016-07-12 09:15:00 Animal: Lion Bird: White Owl Fish: Sword Fish
Time: 2016-07-12 09:15:00
Name: Count:
White Owl 1
Sword Fish 1
Lion 1
このコードが機能する方法は、私たちに有利にオブジェクト指向プログラミングを使用することですログエントリを格納し、特定の形式でログエントリを表現し、特定のプロパティに従ってログエントリを結合するといった作業を単純化する必要があります。
まず、Entry
オブジェクトとそのプロパティ(self.time
、self.animal
、self.bird
、self.fish
)は、ログ内のエントリを表していることに注意してください。プロパティに格納されている情報が正しいと仮定すると、その情報を書式設定された文字列として表すメソッドを作成できます。メソッド__repr__()
は、Pythonがオブジェクトの文字列表現を望んでいるときに呼び出されるので、このコードを置くのが良い場所のようです。このメソッドにはformat
関数が多用されていますが、format
のpythonドキュメントを閲覧した後の動作ははっきりしているはずです。
指定した2番目の出力を取得するには、これらのエントリオブジェクトを組み合わせる方法が必要です。これは多くの方法で行うことができ、私がやったやり方は必ずしも最良ではありません。私は、オブジェクトに+
演算子が使用されたときに呼び出される__radd__()
と__add__()
メソッドを使用しました。これにより、コードentry1 + entry2
またはsum([entry1, entry2])
を使用して、両方の項目の動物の合計を得ることができます。しかし、Entry
クラスは、任意の情報を含むことができないため、合計の結果を格納するために使用することはできません。代わりに、私はオブジェクトを合計した結果にdict
オブジェクトを使用することを選択しました。 2つ以上のオブジェクトを合計するには、Entry
のオブジェクトは、Entry + Entry + Entry
の結果がdict + Entry
であるため、のオブジェクトをdict
のオブジェクトと合計できる必要があります。
__add__()
機能は、オブジェクトが追加されているオブジェクトがdict
オブジェクトであるかどうかをチェックします。この場合、エントリ内の各動物が既にdict
に存在するかどうかをチェックします。もしそうでなければ、動物をキーとして追加します。それ以外の場合は、そのキーの値をインクリメントします。 __radd__()
は、特殊な状況で使用される点を除いて、__add__()
に似ています。詳細については、Pythonのドキュメントを参照してください。オブジェクトがEntry
ある場合、コードは各Entry
物体からの動物のすべてを収集し、その情報からdict
を作成するために書かれたかもしれない場合には
が、dict
とEntry
を追加するためのコードが既に存在するので1つのオブジェクトを空のdict
に追加してから、結果としてdict
をもう1つのEntry
オブジェクトに追加する方が簡単です。
その他のオブジェクトの場合、Entry
は、dict
自身の説明、または空のdict
が追加されたものを返します。
すべてのツールは、前述の目標を達成するために存在します。所望の出力1と一致するEntry
の文字列表現を得るには、print entry
またはstrrepr = str(entry)
が必要です。所望の出力2を得るために、もう少し作業が必要ですが、同じself.time
プロパティを持つすべてのエントリを合計し、結果のdictを表示するだけです。
最後の部分は、ログを解析してEntry
オブジェクトのリストを作成することです。このコードは、ログを1行ずつ表示し、Entry
に情報を入力します。私はこれがかなり簡単だと思っていますが、それが理にかなっていなければ、自由に質問することができます。
これまでに何を試しましたか?現在の実装ではどのような困難がありますか?あなたは最新のコードの試みの[mcve]を提供していただけますか? – idjaw
何らかの方法でファイルを読み込めましたか? – depperm
は期待どおりの出力を示していますか、それともdataformatにミラーリングされているはずですか? – patrick