76044


条件付きでリストの要素にマッチする文字列を消去したいのですが、その際に正規表現の書き方がわかりません。

路線名から社名を除外したいのですが、たまに路線名と社名が一致してしまう例外があります。例えば、「京王井の頭線」、「京王線」という文字列がある場合、「井の頭線」「京王線」という文字列にしたいのですが、私が書いた以下の正規表現では「京王線」が「線」になってしまいます。

[code]

    li = ["東急", "東京メトロ", "西武", "都営", "小田急", "京王", "東武"]
    a = "京王線"
    
    combined = "(" + ")|(".join(li)+ ")"
    a_new = re.sub(combined, "", a)
    a_new
    
    >>> '線'
    
[/code]

したがってリストの要素の文字列の直後に「線」という文字がある場合は消去しないという正規表現を書きたいです。以下の正規表現で特定できると思うのですが、これをリストを用いた正規表現にどう応用すれば良いのかわかりません。もしくは他に良い方法があれば、どなたか教えていただけますでしょうか。

[![画像の説明をここに入力](https://i.stack.imgur.com/2fsZ9.png)](https://i.stack.imgur.com/2fsZ9.png)


CC BY-SA 4.0
2021-05-24T09:58:51.607
76043
2021-05-25T16:08:11.970
2021-05-25T01:27:24.160
3060
45479
question
python 正規表現
リストを用いた正規表現


期待されているのはこんな感じかな？

[code]

    #combined = "(" + ")|(".join(li)+ ")"
    combined = "(?!線)|".join(li)+"(?!線)"
    
[/code]


CC BY-SA 4.0
2021-05-24T10:35:10.243
76044
2021-05-24T10:35:10.243
41756
76043
answer


質問に書かれている路線名の例についてだけで言えば、正規表現を使わずに、  
・入力文字列の先頭が特定の文字列（リストの要素）で始まるとき、それ取り除く  
・取り除いた結果「線」になったら、元の文字列を返す  
という関数を作るといいんじゃないかと。

`startswith()`とか`ret == "線"`とか、そのまま読める感じ(?)のものになります。

例:

[code]

    def remove_company_name(s):
        ret = s
        for p in ["東急", "東京メトロ", "西武", "都営", "小田急", "京王", "東武"]:
            if ret.startswith(p):
                ret = ret[len(p):]  # Python 3.9から ret = ret.removeprefix(p) と書けます
                if ret == "線":
                    ret = s
                break
        return ret
    
    for i in ["京王井の頭線", "京王線"]:
        print(remove_company_name(i))
    
    # 井の頭線
    # 京王線
    
[/code]

質問に書かれているやり方ですと、正規表現を生成するプログラムになっているため、  
ぱっと見でわかりづらいものになっていってしまう印象はあります。


CC BY-SA 4.0
2021-05-25T14:03:01.353
76060
2021-05-25T16:08:11.970
2021-05-25T16:08:11.970
9575
9575
76043
answer