LoginSignup
3
8

More than 1 year has passed since last update.

Pythonのfindメソッドで部分一致文字を避けて文字列の位置を取得したい

Last updated at Posted at 2023-05-13

前書き

リスト内にある各文字列の開始位置と終了位置を取りたい!ってときにfindメソッドを用いたのですが、部分的に一致するものが文章の先にきてしまうと正確な位置ではない値が取れてしまいました。

そこで自分なりに改善してみた結果を以下に書いておきます。

(記事にするようなことでもないですが、アウトプットの癖をつけるためにも、自分の気づきになったことはどんなに小さなことでも残していこうかなと)

問題となった動作

例えば、以下のような文章から「カモシカ」の後に続く、「シカ」という語句の位置を取りたい場合

sample
    カモシカもシカも確かに鹿だが、アシカは確か鹿ではない

以下のようなコードを実行します。
code
    word_list = ["カモシカ", "シカ", "アシカ"]
    text = "カモシカもシカも確かに鹿だが、アシカは確か鹿ではない"
    for word in word_list:
        start_pos = text.find(word) # 開始位置
        end_pos = text.find(word) + len(word) # 終了位置
        print(word, start_pos, end_pos) # (リスト要素, 開始位置, 終了位置)

出力された結果を見ると、「シカ」の文字位置が「カモシカ」と被っていることがわかります。

出力結果
    カモシカ  0 4
    シカ 2 4
    アシカ 15 18

「シカ」の開始位置が5、終了位置が7というのが本来欲しい出力結果ですが、このコードでは前述した通り、そうなっていません。

解決法

スライスを利用することで、改善することができました。

以下にコードを記しておきます。

code
    word_list = ["カモシカ", "シカ", "アシカ"]
    text = "カモシカもシカも確かに鹿だが、アシカは確か鹿ではない"

    #変数を用意して繰り返しの都度、検索する範囲を変更する
    next_search_spos = 0
    for word in word_list:
        start_pos = len(text[:next_search_spos]) + text[next_search_spos:].find(word) # 開始位置
        end_pos =  len(text[:next_search_spos]) + text[next_search_spos:].find(word) + len(word) # 終了位置
        print(word, start_pos, end_pos) # (リスト要素, 開始位置, 終了位置)
        next_search_spos = end_pos

変数を用意して初期値を0に設定し、その後はfor文の最後にそのループ回の語句の終了位置を代入する一文を挟むことで、文字位置の被りを避けることができました。


出力結果
    カモシカ 0 4
    シカ 5 7
    アシカ 15 18

終わりに

今回のやり方が最善なのか、少し不安ながらも存外早くに解決できてよかったです。

研究活動でPythonを使ってはいるものの、プログラムをいじることが少ないのでまだまだ勉強が足りていないと痛感しています。

これからも頑張る:D

追記(2023/05/15) コードに関する注意

この記事に書いたコードではその仕様上、リスト内の要素の順序が文中における出現順でなければならず、仮に「シカ」のみを対象に位置を取りたい場合は正確な出力が得られないことに気づきました。

具体例1
    word_list = ["アシカ", "カモシカ", "シカ"]
具体例2
    word_list = ["シカ"]

上記に挙げたような形態では出力が正確ではなくなります。<_(._.)_>

コメントでご指摘下さりありがとうございます。
精進します!

3
8
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
8