web-dev-qa-db-ja.com

重複するオカレンスを持つ文字列カウント

Pythonでの重複を含む、特定の文字列の出現回数をカウントする最良の方法は何ですか?それは最も明白な方法ですか:

def function(string, str_to_search_for):
      count = 0
      for x in xrange(len(string) - len(str_to_search_for) + 1):
           if string[x:x+len(str_to_search_for)] == str_to_search_for:
                count += 1
      return count


function('1011101111','11')
returns 5

またはPythonでより良い方法がありますか?

50
calccrypto

さて、これはmight Cでの比較を行うので高速です:

def occurrences(string, sub):
    count = start = 0
    while True:
        start = string.find(sub, start) + 1
        if start > 0:
            count+=1
        else:
            return count
69
Jochen Ritzel
>>> import re
>>> text = '1011101111'
>>> len(re.findall('(?=11)', text))
5

マッチのリスト全体をメモリにロードしたくない場合、これは問題になりません!本当に望むならこれを行うことができます:

>>> sum(1 for _ in re.finditer('(?=11)', text))
5

関数として(re.escapeは、部分文字列が正規表現に干渉しないことを確認します)。

>>> def occurrences(text, sub):
        return len(re.findall('(?={0})'.format(re.escape(sub)), text))

>>> occurrences(text, '11')
5
38
jamylak

new Python regex module ]を使用して試すこともできます。これは重複する一致をサポートします。

import regex as re

def count_overlapping(text, search_for):
    return len(re.findall(search_for, text, overlapped=True))

count_overlapping('1011101111','11')  # 5
11
David C

Pythonのstr.countは、重複しない部分文字列をカウントします。

In [3]: "ababa".count("aba")
Out[3]: 1

重複するシーケンスをカウントする方法はいくつかありますが、もっとたくさんあると思います:)

先読み正規表現

正規表現で重複する一致を見つける方法?

In [10]: re.findall("a(?=ba)", "ababa")
Out[10]: ['a', 'a']

すべての部分文字列を生成

In [11]: data = "ababa"
In [17]: sum(1 for i in range(len(data)) if data.startswith("aba", i))
Out[17]: 2
9
Dima Tisnek
s = "bobobob"
sub = "bob"
ln = len(sub)
print(sum(sub == s[i:i+ln] for i in xrange(len(s)-(ln-1))))
3

重複する別の文字列でパターンを見つける方法

この関数(別のソリューション!)は、パターンとテキストを受け取ります。とその位置にあるすべての部分文字列を含むリストを返します。

def occurrences(pattern, text):
    """
    input: search a pattern (regular expression) in a text
    returns: a list of substrings and their positions 
    """
    p = re.compile('(?=({0}))'.format(pattern))
    matches = re.finditer(p, text)
    return [(match.group(1), match.start()) for match in matches]

print (occurrences('ana', 'banana'))
print (occurrences('.ana', 'Banana-fana fo-fana'))

[( 'ana'、1)、( 'ana'、3)]
[( 'Bana'、0)、( 'nana'、2)、( 'fana'、7)、( 'fana'、15)]

3
def count_substring(string, sub_string):
    count = 0
    for pos in range(len(string)):
        if string[pos:].startswith(sub_string):
            count += 1
    return count

これが最も簡単な方法です。

2
Arun Tom

コースのボブの質問に対する私の答え:

s = 'azcbobobegghaklbob'
total = 0
for i in range(len(s)-2):
    if s[i:i+3] == 'bob':
        total += 1
print 'number of times bob occurs is: ', total
2
Luke D

ここではリストの内包表記を使用するのがかなりPython的な方法ですが、おそらく最も効率的ではありません。

sequence = 'abaaadcaaaa'
substr = 'aa'

counts = sum([
    sequence.startswith(sub, i) for i in range(len(sequence))
])
print(counts)  # 5

リストは[False, False, True, False, False, False, True, True, False, False]になります。これは、文字列を介してすべてのインデックスをチェックするためです。int(True) == 1であるため、sumは一致の総数を示します。

1
ParkerD
def count_substring(string, sub_string):
    counter = 0
    for i in range(len(string)):
        if string[i:].startswith(sub_string):
        counter = counter + 1
    return counter

上記のコードは、文字列全体を一度ループし、カウントされている特定の部分文字列で始まる文字列があるかどうかをチェックし続けます。

1
Anshul Tiwari

ここに私のedX MIT "find bob" *ソリューション(* sという名前の文字列内の "bob"オカレンスの数を検索)があります。

s = 'azcbobobegghakl'
count = 0

while 'bob' in s:
    count += 1 
    s = s[(s.find('bob') + 2):]

print "Number of times bob occurs is: {}".format(count)
1
dasdachs

これは正規表現を使用して解決できます。

import re
def function(string, sub_string):
    match = re.findall('(?='+sub_string+')',string)
    return len(match)
1

文字列が大きい場合、要約では Rabin-Karp を使用します。

  • 文字列上を移動する部分文字列サイズのローリングウィンドウ
  • O(1)追加および削除のオーバーヘッド(1文字ずつ移動)のハッシュ)
  • cで実装されるか、pypyに依存する
0
Dima Tisnek

これはstr.find()を使用する別の例ですが、答えが多いため、必要以上に複雑になっています。

def occurrences(text, sub):
    c, n = 0, text.find(sub)
    while n != -1:
        c += 1
        n = text.find(sub, n+1)
    return c

In []:
occurrences('1011101111', '11')

Out[]:
5
0
AChampion

部分文字列の出現をカウントする簡単な方法は、count()を使用することです。

_>>> s = 'bobob'
>>> s.count('bob')
1
_

重複する部分がわかっている場合は、replace ()を使用して重複する文字列を見つけることができます。

_>>> s = 'bobob'
>>> s.replace('b', 'bb').count('bob')
2
_

静的であることに加えて、他の制限があることに注意してください。

_>>> s = 'aaa'
>>> count('aa') # there must be two occurrences
1 
>>> s.replace('a', 'aa').count('aa')
3
_
0
danbros

Given

sequence = '1011101111'
sub = "11"

コード

この特定の場合:

sum(x == Tuple(sub) for x in Zip(sequence, sequence[1:]))
# 5

より一般的には、これ

windows = Zip(*([sequence[i:] for i, _ in enumerate(sequence)][:len(sub)]))
sum(x == Tuple(sub) for x in windows)
# 5

またはジェネレーターに拡張:

import itertools as it


iter_ = (sequence[i:] for i, _ in enumerate(sequence))
windows = Zip(*(it.islice(iter_, None, len(sub))))
sum(x == Tuple(sub) for x in windows)

代替

more_itertools.locate

import more_itertools as mit


len(list(mit.locate(sequence, pred=lambda *args: args == Tuple(sub), window_size=len(sub))))
# 5
0
pylang

入力として2つの文字列を取り、重複を含む文字列でsubが発生する回数をカウントする関数。 subが部分文字列かどうかを確認するために、in演算子を使用しました。

def count_Occurrences(string, sub):
    count=0
    for i in range(0, len(string)-len(sub)+1):
        if sub in string[i:i+len(sub)]:
            count=count+1
    print 'Number of times sub occurs in string (including overlaps): ', count
0
Aquila3000

複製された question の場合、3で3カウントし、文字列を比較することにしました。

counted = 0

for i in range(len(string)):

    if string[i*3:(i+1)*3] == 'xox':
       counted = counted +1

print counted
0
AndreL
def count_overlaps (string, look_for):
    start   = 0
    matches = 0

    while True:
        start = string.find (look_for, start)
        if start < 0:
            break

        start   += 1
        matches += 1

    return matches

print count_overlaps ('abrabra', 'abra')
0
doublep

受け入れられた答えに非常に近い代替方法ですが、ループ内にwhileを含める代わりにifテストとしてifを使用します。

def countSubstr(string, sub):
    count = 0
    while sub in string:
        count += 1
        string = string[string.find(sub) + 1:]
    return count;

これにより、while True:そして私の意見では少しきれいです

0
stevoblevo