3

find や index.. などの Python の定義済み関数を使用せずに、文字列が別の文字列に存在するかどうかを確認しようとしています。

現在、私の関数は 2 つの文字列をパラメーターとして取ります。1 つは検索する文字列で、もう 1 つの文字列は最初の文字列で探しているものです。

2 番目の文字列が最初の文字列に存在する場合、関数が最初の文字列で発生するすべての位置を返すようにします。

現在、私の関数は最初のオカレンスを見つけてインデックスを返すことができますが、最初のオカレンスだけでなく、複数のオカレンスを見つけたいと思っています。

以下は私のコードです:

def multi_find (s, r):

    s_len = len(s)
    r_len = len(r)

    if s_len < r_len:
        n = -1
    else:
        m = s_len - r_len
        n = -1  # assume r is not yet found in s
        i = 0

        while n == -1 and i < m:
            # search for r in s until not enough characters are left
            if s[i:i + r_len] == r:
                n = i
            else:
                i = i + 1
    print (n)

multi_find("abcdefabc. asdli! ndsf acba saa abe?", "abc")

現時点では、abc が最初に発生する場所であるため、これは「0」のみを出力します。「0」と「6」(2 回目の発生の始まり) を返すようにするにはどうすればよいですか。

発生するすべての場所のリストを作成し、そのリストに i を追加するようなことを考えていましたが、それを試してみたところ、何もうまくいきませんでした。

4

7 に答える 7

8

できるよ:

>>> haystack = "abcdefabc. asdli! ndsf acba saa abe?"
>>> needle = "abc"
>>> for i, _ in enumerate(haystack):
...     if haystack[i:i + len(needle)] == needle:
...         print (i)
...
0
6
于 2013-11-07T17:37:25.997 に答える
3

を使用した別の代替手段regex

>>> import re
>>> haystack = "abcdefabc. asdli! ndsf acba saa abe?"
>>> needle = "abc"
>>> [m.start() for m in re.finditer(r'{}'.format(re.escape(needle)), haystack)]
[0, 6]

上記の解決策は、 に3 つ 'aa'あるように、部分文字列が重なっている場合には機能しません'aaaa'。したがって、重複する一致も見つけたい場合は、次のようにします。

>>> haystack = "bobob"
>>> needle = "bob"
>>> [m.start() for m in re.finditer(r'(?={})'.format(re.escape(needle)), haystack)]
[0, 2]
于 2013-11-07T17:47:16.237 に答える
1
def multi_find (s, r):
    s_len = len(s)
    r_len = len(r)
    n = [] # assume r is not yet found in s

    if s_len >= r_len:
        m = s_len - r_len
        i = 0

        while i < m:
            # search for r in s until not enough characters are left
            if s[i:i + r_len] == r:
                n.append(i)
            i = i + 1
    print (n)

multi_find("abcdefabc. asdli! ndsf acba saa abe?", "abc")

n をリストに置き換えるだけで、見つけた値を追加し続けることができます。また、一致が見つかった場合でも i をインクリメントする必要があります。一致が見つかるとすぐに停止する while n == -1 制約があったことを除いて、永遠にループに陥っていたでしょう。

于 2013-11-07T17:51:27.517 に答える
1
def multi_find(s, r):

    s_len = len(s)
    r_len = len(r)

    _complete = []

    if s_len < r_len:
        n = -1
    else:

        for i in xrange(s_len):
            # search for r in s until not enough characters are left
            if s[i:i + r_len] == r:
                _complete.append(i)
            else:
                i = i + 1
    print(_complete)

multi_find("abcdefabc. asdli! ndsf abc saa abe?", "abc")
于 2013-11-07T17:43:46.350 に答える
1

おそらくこれを行う最善の方法は、find 関数を呼び出し続けることです (これも最速です)。

def multifind(string, value, start = 0, stop = None):
    values = []
    while True:
        found = string.find(value, start, stop)
        if found == -1:
            break
        values.append(found)
        start = found + 1
    return values

print multifind('hello abc abc', 'abc')

出力:

[6, 10]
于 2013-11-07T18:00:55.043 に答える
0

注:ここでのこの回答は、まだ良い「教育的な回答」だと思います。再帰なしで、このスレッドの他の場所でより良い解決策を提出しました。

def multi_find(s, r, start=0):
    if start >= len(s): 
        return []
    if s.startswith(r, start):
        return [start] + multi_find(s, r, start+1)
    else:
        return multi_find(s, r, start+1)

これにより、オプションのstart位置を渡して で検索を開始できますs

このソリューションは再帰的であり、最速の実装である場合とそうでない場合がありますが、正しく、コードが の各位置での 3 つの可能性のそれぞれを簡単に識別できるようになると思いますs

  1. の終わりs
  2. 別のものを見つけたr
  3. 他に見つけられなかったr
于 2013-11-07T18:10:11.930 に答える