teratail header banner
teratail header banner
質問するログイン新規登録

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

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

新規登録して質問してみよう
ただいま回答率
85.30%
Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

542閲覧

findメソッドと同じ動作をする関数my_find(s,t)を作りたいです。

nekopota.

総合スコア22

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2022/10/05 05:55

0

0

前提

ここに質問の内容を詳しく書いてください。
(例)
pythonでメソッド s.find(t) と同じ動作をする関数 my_find(s, t) を実装したいです。
my_find(s,t)ではfor文と文字列 s に対し,s.startswith(t, i) は,s の i 番目の文字から始まる部分文字列が t と一致するとき True, そうでないとき False を返す関数を使って実行したいです。

実現したいこと

ここに実現したいことを箇条書きで書いてください。
文字列 s に対し、s が部分文字列として t を含むならば,その最初の出現位置を返し、s が部分文字列として t を含まないならば,-1 を返す関数をfindメソッドを使わずに作りたいです。(新しく作りたい関数をmy_find(s,t)とします。)
また、s.startswith(t, i) と同じ動作をする関数 my_startswith(s, t, i)を自分で作ったのでmy_startswith(s,t,i)とfor文を、関数my_find(s,t)の中で使いたいです。

発生している問題・エラーメッセージ

エラーメッセージ

該当のソースコード

文字列 s に対し、s の i 番目の文字から始まる部分文字列が t と一致するとき True, そうでないとき False を返すs.startswith(t, i) と同じ動作をするものをまず作りました。

def my_startswith(s, t, i): # t[0], t[1], ..., t[len(t)-1] が # s[i], s[i+1], ..., s[i+len(t)-1] と # 同じかどうか調べる for j in range(0, len(t)): if len(s)-i < len(t): return False if s[i + j] != t[j]: # 異なる文字があった return False return True

上の関数を使って、文字列 s に対し、s が部分文字列として t を含むならば,その最初の出現位置を返し、s が部分文字列として t を含まないならば,-1 を返すmy_find(s,t)を作成しようとしました。

# 入力: # s : 文字列 # t : 文字列 # 出力: # s が t を含むならその最初の出現位置 # それ以外のとき -1 def my_find(s, t): for i in range(0,len(s)): if my_startswith(s,t,i)==True: return i if len(s)-i < len(t): return i else: return -1

しかし上のコードだと
s = "abracadabra"
my_find(s, "cad")
を実行したときに正しい出力は4なのに-と表示されてしまいます。
iの範囲が間違っていると思い範囲を色々変えてみたのですがうまくいきません。
分かりにくい説明で申し訳ないのですが、ご教授ください。

試したこと

上のコードを作り実行してみました。

補足情報(FW/ツールのバージョンなど)

my_find(s, t) は,my_startswith(s, t, i) が True になる
最小の i を return すればよい

for i in range(....): # range の引数がよく分かりませんでした
もし my_startswith(s, t, i) が成り立てば
return i
return -1 # ループ中いちども my_startswith(s, t, i) が True にならなかった場合
このように考えています。よろしくお願いします。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

melian

2022/10/05 06:17 編集

my_find 関数の、 else: return -1 に誤認があります。ループ実行の最初の段階(i == 0)で return -1 が実行されてしまいます。
nekopota.

2022/10/05 06:32

文字列の3番目や4番目が同じであっても1つ目の数(i==0)が同じではなかったら-1が返されてしまうということですか!すごく分かりやすい説明ありがとうございます。それを踏まえて else: return -1 の部分を if my_startswith(s,t,i)==False: return -1 に変えてみたのですがうまく実行することができませんでした。間違いがあれば教えていただきたいです。
melian

2022/10/05 06:40

return -1 は for ループが終了した後に置きます。※ 全角スペースでインデントを付けています def my_find(s, t):  for i in range(0,len(s)):   if my_startswith(s,t,i)==True:    return i   if len(s)-i < len(t):    return i  return -1
nekopota.

2022/10/05 06:47

ご丁寧にありがとうございます。正しく実行することができました。 for文の中で何が繰り返されているかきちんと確認しながらコードを書くように気をつけます! 本当にありがとうございました。とても助かりました。
guest

回答1

0

自己解決

melianさんが教えてくださいました。

def my_find(s, t):  for i in range(0,len(s)):   if my_startswith(s,t,i)==True:    return i   if len(s)-i < len(t):    return i  return -1

投稿2022/10/05 06:48

nekopota.

総合スコア22

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

can110

2022/10/05 07:09

解決されていますが、s,t='a','ab'の場合の結果がs.find(t)と同じか確認してみてください。 そのうえでmy_find関数内の「if len(s)-i < len(t):」の判定の意図、正しいかをいまいちど考えてみてください。
nekopota.

2022/10/05 07:28

同じ0になりました。「if len(s)-i < len(t):」は関数の中になくても大丈夫ということでしょうか?
can110

2022/10/05 07:57

s,t='a','ab'の場合、s.find(t)は0になりますか? こちらで「print('a'.find('ab'))」と実行したら「-1」になります。
nekopota.

2022/10/05 08:38

もう一度やり直してみました。どちらも-1になりました。 同じ文字を含んでいるのに含んでいない扱いにされてしまっているのでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.30%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問