2017-01-19 8 views
1

私はピクルスにいます。2つの異なるリストをマップする

私はdd内のヘッダーとフッターを探しています。

ヘッダーが見つかったら、それをリストの中に入れます。フッターも同様です。

しかし、ヘッダーの前にフッターが見つかることがあることに気付きました。この場合、ヘッダーリストが空であるかどうかを確認します。フッターを無視します。 これは正常に動作します。

if not header: 
     footer.append(myfooter) 

しかし、たぶん私はヘッダーを見つけた後、2つのフッター、そしてヘッダーを再度見つけます。これらはリストに追加されます - これは私が目指しているものではありません。

私の目標は、ヘッダーをフッターに直接マッピングすることです。したがって、2つのリストは常に同じ量を持つべきです、またはヘッダーリストはフッターリストより大きくなければなりません。

それに応じてアルゴリズムを実装する方法はありますか?

+0

括弧が私に似ています。最も簡単な解決策の1つは、スタックを使用することです。https://interactivepython.org/runestone/static/pythonds/BasicDS/SimpleBalancedParentheses.html –

+0

したがって、見つかったすべてのヘッダーに最初に使用されていない(マップされていない)フッタが見つかるようにしますヘッダーの後ろに右? –

答えて

0

最後に表示された項目がヘッダーの場合にのみ、フッターをリストに追加します。それはあなたがしたいことですか?

+1

ヘッダーが見つかったときにtrueになるブール値を追加し、フッターステートメントでこのヘッダーが真であるかどうかを確認するか、ヘッダーが空でないかどうかをチェックします(ヘッダー、ヘッダーを見つけることができます)。 ? @Moberg – user7440299

+0

はい私はそう思います。 :) – Moberg

0

これは何ですか?私は 'dd'が何であるか分からず、ヘッダーとフッターは特定の方法で始まる1行であると思っています。ユースケースに合わせてヘッダーとフッターに一致するロジックを置き換える必要があります。

import re 

VALID_DOCUMENT_A = \ 
""" 
header: 1 
Hi there. 
This is the body of page 1. 
footer: 1 
header: 2 
This is the second page. 
footer: 2 
""" 

VALID_DOCUMENT_B = \ 
""" 
header: 1 
Hi there. 
This is the body of page 1. 
footer: 1 
header: 2 
This is the second page. 
footer: 2 
header: 3 
This third page has a header but no footer. 
""" 

INVALID_DOCUMENT_A = \ 
""" 
header: 1 
Hi there. 
This is the body of page 1. 
footer: 1 
This is the second page. Where's the header, though? 
footer: 2 
""" 

INVALID_DOCUMENT_B = \ 
""" 
header: 1 
Hi there. 
This is the body of page 1. 
footer: 1a 
footer: 1b 
This is the second page. Oops - two footers above. 
footer: 2 
""" 

INVALID_DOCUMENT_C = \ 
""" 
header: 1 
Hi there. 
This is the body of page 1. 
footer: 1 
header: 2a 
header: 2b 
This is the second page. Oops - two headers above. 
footer: 2 
""" 


def is_header(line): 
    return re.match('^header:.*', line) 


def is_footer(line): 
    return re.match('^footer:.*', line) 


def pair_headers_and_footers(text): 
    lines = text.splitlines() 

    stack = [] 
    for i, line in enumerate(lines, 1): 
     if is_header(line): 
      if stack: 
       raise ValueError('Got unexpected header on line {}'.format(i)) 

      stack.append(line) 

     elif is_footer(line): 
      if not stack: 
       raise ValueError('Got unexpected footer on line {}'.format(i)) 

      yield stack.pop(), line 


if __name__ == '__main__': 
    documents = [ 
     VALID_DOCUMENT_A, # 2 headers, 2 footers 
     VALID_DOCUMENT_B, # 3 headers, 2 footers 
     INVALID_DOCUMENT_A, # missing header for page 1 
     INVALID_DOCUMENT_B, # multiple footers for page 1 
     INVALID_DOCUMENT_C # multiple headers for page 2 
    ] 

    for document in documents: 
     try: 
      print(list(pair_headers_and_footers(document))) 
     except ValueError as e: 
      print(e) 

出力

[('header: 1', 'footer: 1'), ('header: 2', 'footer: 2')] 
[('header: 1', 'footer: 1'), ('header: 2', 'footer: 2')] 
Got unexpected footer on line 7 
Got unexpected footer on line 6 
Got unexpected header on line 7 

補遺

私は機能pair_headers_and_footersに、あなたは置き換えることができることを追加する必要があります:

lines = text.splitlines() 

をして:

lines = (m.group(0).rstrip() for m in re.finditer('(.*\n|.+$)', text)) 

これは、特に大量のテキストを処理している場合など、メモリ使用量を減らすのに役立ちます。この変更により、ヘッダーとフッターのペアリングのプロセス全体が「怠け者」になります。

+0

多くの感謝の言葉をいただきましたが、それはあまりにも進んでいたかもしれませんが、他の答えは自分の考え方に適していました。私はまだPythonにはまったく新しいです。 – user7440299

+0

@ user7440299あなたが最良の仲間を助けるものであれば何の心配もありません。 – Tagc

関連する問題