質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.06%

正規表現にfor文は使えない?

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 169

score 62

問題

イメージ説明
ABC122 B問題より

方針

本来であれば部分文字列は高々制約上56個までしか発生しないので、これを全探索すれば良いのですが、正規表現を用いた解法も無理ではなさそうと思い、やってみます。

コード

入力例にある、'HATAGAYA'(この文字列に対する最長のACGT文字列は'ATAGA')を念頭に考えてみます:

import re

name = 'HATAGAYA'
li = []
for i in range(9):
    li.append(re.search(r'[A.T.G.C]{i}', name))

print(li)

出力

[None, None, None, None, None, None, None, None, None]

考察・質問

おそらく{i}で指定したい部分文字列の長さを(ダブル)クオーテーションで囲ってしまっているが故、for i in range の i と {i} の i が対応していない為、Noneだらけのリストが返されているというところまでは考えられております。しかしながら、
li.append(re.search(r'[A.T.G.C]{0}', name)), 
li.append(re.search(r'[A.T.G.C]{1}', name)),
li.append(re.search(r'[A.T.G.C]{2}', name)),...
とやっていくのは正直あまりにアホらしいので、何か方策を練りたいところなのですが、上のやり方でのfor文の使用が封印されてしまっている為、詰まっております。何か近いやり方での解決策は存在しますでしょうか。雑な質問とはなってしまいましたが、お力添え頂ける箇所がございましたら、ご教授のほどよろしくお願い申し上げます。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+1

次のようにして、文字列に変数を埋め込みます。

for 略:
    li.append(re.search(fr'[A.T.G.C]{{{i}}}', name))

{{ は { のエスケープ表現です。}} も然り。
f文字列で {i} に i が埋め込まれた結果、[A.T.G.C]{2} みたいな文字列が作られます。

ただし

正規表現として [A.T.G.C] は明らかにおかしく、これは [ATGC] の誤りでしょう。

別解

for文を使わずとも、次のようにfindallで全抽出すれば充分に思います。

name = 'HATAGAYA'
chunks = re.findall(r'[ATGC]+', name)

ATGC文字列のリストが得られるので、一番長いものを選べば良いです。
特にこの問題の場合長さが求められれば良いので、max(map(len, chunks)) で足ります。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2021/05/04 23:42

    ご丁寧にありがとうございました。示して頂いた全方法で、実行することができました。

    キャンセル

+1

f文字列で埋め込めます
{}は2つ重ねればエスケープできます

i = 1
s = f'[A.T.G.C]{{{i}}}'

assert s == r'[A.T.G.C]{1}'

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+1

正規表現には「最長一致の法則」というのがあるので、シンプルにマッチさせれば自動的に「最も長いACGT文字列」が得られるはずです。

いろいろ問題がありました。すいません。

import re

name = 'HATAGAYA'
acgt_string = re.search(r'[ACGT]+', a).string

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2021/05/04 23:29 編集

    ・ ご提示のコードは実行できません。(変数名が違うだけで、これはクリティカルな問題では無いです)

    ・ マッチオブジェクトのstring属性はマッチ対象の文字列全体を返しますから、そこからマッチ結果を知ることはできません。

    ・ 最長一致と言うのは、「できるだけ長くマッチしようとする」法則であって、「一番長いマッチ文字列を探す」ものでは無いと認識しています。実際Pythonで HATAGAYA_AACCGGTT を対象に試してみましても、マッチするのは ATAGA であって AACCGGTT では無いです。https://wandbox.org/permlink/9RNOHsNYr2a7q5Xb

    キャンセル

  • 2021/05/05 00:16

    ああそうか、「短いACGT文字列」が本来得られるべき「最長の文字列」よりも前に存在しているかもしれない可能性を忘れていました。しかもstringが期待どおりの値を返さない。面目ない…最近こういうパターンが多いな。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.06%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る