再帰を使用して文字列内に複数の部分文字列インデックスを表示する

def subStringMatchExact(target, key):

    if (target.find(key) == -1):
        return []
    else:
        foundStringAt = [target.find(key)]
        target = target[foundStringAt[0] + len(key):]
        return foundStringAt + subStringMatchExact(target, key)

string = subStringMatchExact("your code works with wrongly correlated coefficients which incorporates more costs", "co") 

print(string)

現在の間違った出力:

[5, 22, 9, 19, 14]

前の再帰ステップで部分文字列の長さを合計するのに問題があります。 len(previousSubstring)+ len(key) - 1 + len(currentSubstring)のように、リストの2番目の要素は 22 コード>。

私のコードを改善したり、私のエラーを修正するためのアイデアはありますか?

2
私は、 print()によって、これがPython 3であると思いますか?
追加された 著者 juliomalegria,

4 答え

速い道

独自のソリューションを実装する必要はありません。すでに完成しています。 re モジュールの finditer 関数を使用します。

>>> import re
>>> s = 'your code works with wrongly correlated coefficients which incorporates more costs'
>>> matches = re.finditer('co', s)
>>> positions = [ match.start() for match in matches ]
>>> positions
[5, 29, 40, 61, 77]

あなた自身の方法

再帰を使用して独自の実装を作成する場合は、 str.find 関数の余分な引数を利用できます。 help(str.find)には次のようなことが書かれています:

S.find(sub [,start [,end]]) -> int

    Return the lowest index in S where substring sub is found,
    such that sub is contained within s[start:end].  Optional
    arguments start and end are interpreted as in slice notation.

    Return -1 on failure.

str.find に部分文字列の検索を開始する場所を指示する start という余分な引数があります。それだけで必要なのです!

したがって、実装を変更すると、シンプルで高速で美しいソリューションを得ることができます。

def substring_match_exact(pattern, string, where_should_I_start=0):
    # Save the result in a variable to avoid doing the same thing twice
    pos = string.find(pattern, where_should_I_start)
    if pos == -1:
        # Not found!
        return []
    # No need for an else statement
    return [pos] + substring_match_exact(pattern, string, pos + len(key))

ここでは再帰は何ですか?

  • 最初に、位置0から始まる文字列の部分文字列を検索しています。
  • 部分文字列が見つからなかった場合、空のリストが [] に返されます。
  • 部分文字列が見つかった場合は、 [pos] pos +位置に文字列開始 len(key)

私たちの新しい機能を使用する

>>> s = 'your code works with wrongly correlated coefficients which incorporates more costs'
>>> substring_match_exact('co', s)
[5, 29, 40, 61, 77]
5
追加された
ああ、正規表現。私はそれを効率的に行う方法を知っていますが、私のコードにはまだ入力がありますか?私はMIT 6.00 OCWをやっていて、ちょうど再帰について読んでいます。だから私は再帰によってそれをすることに集中しているのです。トピックの背後にある理論を知っていますが、この「難しい」実践的な問題を解決したいと思います。 FactorialsとFibonacciは、私がこの概念を正しく把握するのが容易ではありませんでした。
追加された 著者 crzrcn,
すべての基本的なプログラミング問題は宿題問題とみなすことができるので、私はあなたの "解決策"を提供することを躊躇しています(オフセットアプローチについて言及するだけで十分です)。しかし、reモジュールの入力には非常に感謝しています。それについて知らなかった。編集:これはあなたの編集を見た前に、ありがとう再びありがとう。
追加された 著者 crzrcn,
いい答えだ! matches = re.finditer( 'co'、s);)に一致するようにしてください。
追加された 著者 Tuxdude,
@cRaZiRiCaN:再帰は確かに非常に興味深い概念です。他の答えを見て、あなたのソリューションの問題点を十分に理解してください。
追加された 著者 juliomalegria,
@cRaZiRiCaN私の答えを編集しました
追加された 著者 juliomalegria,

現在、コードで元の文字列ではなく短縮された文字列内の co <​​/ code>のインデックスを検索しようとしています。したがって、 [5、22、9、19、14] が間違っているように見えるかもしれませんが、スクリプトは、以下のスクリプトのように、オフセットを含めることで、このコードが動作する可能性があります。

def subStringMatchExact(target, key, offset=0): # note the addition of offset

    if (target.find(key) == -1):
        return []
    else:
        foundStringAt = target.find(key)
        target = target[foundStringAt + len(key):]
        foundStringAt += offset # added
        return [foundStringAt] + subStringMatchExact(target, key, foundStringAt + len(key))
        # added foundStringAt + len(key) part

string = subStringMatchExact("your code works with wrongly correlated coefficients which incorporates more costs", "co") 
# no need to call w/ 0 since offset defaults to 0 if no offset is given

print(string)

最初から foundStringAt を作成することは、すべての [0]でオーバーヘッドを追加するため、 インデックスルックアップ。代わりに、 list の戻り値の型が必要なので、return文の中の [] に(my codeのように)囲んでください。

4
追加された
「オーバーヘッド」は問題ではありません。複雑さはあります。
追加された 著者 Karl Knechtel,

それぞれの部分文字列内の位置を常に追加しています。に

return foundStringAt + subStringMatchExact(target, key)

関数呼び出しの結果は、 target = target len(key):]

したがって、この値を関数呼び出しの結果に正確に追加する必要があります。

    foundStringAt = target.find(key)
    offset = foundStringAt + len(key)
    target = target[offset:]
    return [foundStringAt] + [i + offset for i in subStringMatchExact(target, key)]

トリック(未テスト)を行う必要があります。

2
追加された
+1は私よりもpythonic答えをコーディングする。
追加された 著者 Edwin,

私は、運動の場合を除いて、このために再帰を使用することは気にしません。

問題を解決するには:

以前の再帰ステップで部分文字列の長さを合計するのに問題があります。

あなたが本当に "合計"したいのは、既に検索された文字列の量です。これをパラメータとして関数に渡し(最初の呼び出しでは0を使用)、現在削除されている文字列( foundStringAt [0] + len(key):)を再帰呼び出し。

書式設定の問題として(そして、名前に対応しやすくするために)、 foundStringAt に(1要素リストの代わりに)結果を直接格納させ、再帰呼び出しで式の一部として折り返されます。

0
追加された