前提・実現したいこと
1行のテキストに空白区切りで英単語が含まれています。
このテキストに対して重複する単語を初回登場分だけ残して削除するというプログラムを書きたいと考えています。
発生している問題・エラーメッセージ
重複する単語の最後だけを残すマッチパタンはそれっぽく動くようになったので、
現在のプログラムでは以下のような仕様にしています。
- 単語の順番を逆にする
- 重複する単語の最後だけを残して抽出
- 逆順にして元の出現順に
これを、正規表現の置換だけで一発処理できるようにできないでしょうか。
該当のソースコード
python
1import re 2def remove_duplicate(txt): 3 rev_txt = ' '.join(reversed(txt.split())) # 単語を逆順にしたテキストをつくる 4 unique_words = re.findall(r'\b(\w+)\b(?!.*\b\1\b)', rev_txt) # 重複する単語は最後だけ残して抽出 5 return ' '.join(reversed(unique_words)) # 元々の順番に戻す 6 7 8# 以下は動作チェック用 9from collections import OrderedDict 10def check_remove_duplicate(txt): 11 return ' '.join(OrderedDict({w: '' for w in txt.split()})) 12 13test_patterns = [ 14 ['ten ten ten', 'ten'], 15 ['one two three', 'one two three'], 16 ['one two one one ten ten', 'one two ten'], 17 ['one two one one three', 'one two three'], 18 ['four three two one one two three four', 'four three two one'], 19 ['one eno one one oneone one eno oneeno', 'one eno oneone oneeno'], 20 ['a for a in aa if a is b and b in aa', 'a for in aa if is b and'], 21 ['as we know there are known knowns there are things we know that we know there are known unknowns there are things that we now know we do not know there are also unknown unknowns there are things we do not know we do not know', 22 'as we know there are known knowns things that unknowns now do not also unknown'], 23 ['', ''], 24] 25 26 27for s, exp in test_patterns: 28 res = remove_duplicate(s) 29 assert res == exp, res 30 assert res == check_remove_duplicate(s), res
試したこと
後読み機能でうまくマッチパタンを書けないか試してみましたが、pythonの正規表現では後読みは固定長のパタンしか使用できないようなので、あきらめました。
補足情報(FW/ツールのバージョンなど)
python 3.6.x
追記
単語の順番を反転させずに済む方法も考えてみましたが、処理が遅いです。
python
1def remove_duplicate(txt): 2 unique_words = re.findall(r'\b(\w+)\b(?!.*\b\1\b)', txt) # ユニークな単語を抽出 (単語が最後に登場する順番) 3 return ' '.join(sorted(unique_words, key=lambda x: re.search(r'\b{}\b'.format(x), txt).start())) # 単語の最初の出現位置でソート
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2018/07/17 09:09