सबस्ट्रिंग की सभी घटनाओं का पता कैसे लगाएं?


365

अजगर है string.find()और string.rfind()एक स्ट्रिंग में सबस्ट्रिंग के सूचकांक प्राप्त करने के लिए।

मैं सोच रहा हूं कि क्या ऐसा कुछ है string.find_all()जो सभी पाए गए अनुक्रमितों को वापस कर सकता है (न केवल शुरुआत से पहला या अंत से पहला)।

उदाहरण के लिए:

string = "test test test test"

print string.find('test') # 0
print string.rfind('test') # 15

#this is the goal
print string.find_all('test') # [0,5,10,15]

11
क्या 'ttt'.find_all('tt')लौटना चाहिए ?
सैंटियागो एलेसेंड्री

2
उसे '0' वापस करना चाहिए। निश्चित रूप से, संपूर्ण विश्व में भी ऐसा होना चाहिए 'ttt'.rfind_all('tt'), जो
nukl

जवाबों:


523

कोई सरल अंतर्निहित स्ट्रिंग फ़ंक्शन नहीं है जो आप देख रहे हैं, लेकिन आप अधिक शक्तिशाली नियमित अभिव्यक्ति का उपयोग कर सकते हैं :

import re
[m.start() for m in re.finditer('test', 'test test test test')]
#[0, 5, 10, 15]

यदि आप ओवरलैपिंग मैच ढूंढना चाहते हैं, तो लुकहेड ऐसा करेगा:

[m.start() for m in re.finditer('(?=tt)', 'ttt')]
#[0, 1]

यदि आप ओवरलैप के बिना एक रिवर्स खोज-सभी चाहते हैं, तो आप सकारात्मक और नकारात्मक रूप को एक अभिव्यक्ति में जोड़ सकते हैं:

search = 'tt'
[m.start() for m in re.finditer('(?=%s)(?!.{1,%d}%s)' % (search, len(search)-1, search), 'ttt')]
#[1]

re.finditerएक जनरेटर लौटाता है , इसलिए आप एक सूची के बजाय एक जनरेटर प्राप्त []करने के ()लिए उपरोक्त में बदलाव कर सकते हैं जो अधिक कुशल होगा यदि आप केवल एक बार परिणामों के माध्यम से पुनरावृत्ति कर रहे हैं।


नमस्ते, इस के विषय में [m.start() for m in re.finditer('test', 'test test test test')], हम कैसे testया के लिए देख सकते हैं text? क्या यह बहुत अधिक जटिल हो जाता है?
xpanta

7
आप सामान्य रूप से नियमित अभिव्यक्ति देखना चाहते हैं: docs.python.org/2/howto/regex.html । आपके प्रश्न का हल होगा: [m.start () in m for re.finditer ('te [sx] t', 'text test text test')]
Yotam Vaknin

1
इस पद्धति का उपयोग करने की समय जटिलता क्या होगी?
प्रांजल मित्तल

1
@PranjalMittal। ऊपरी या निचला बाउंड? सबसे अच्छा, सबसे खराब या औसत मामला?
मैड

@marcog क्या होगा अगर सबस्ट्रिंग में कोष्ठक या अन्य विशेष वर्ण हैं?
बनानच

109
>>> help(str.find)
Help on method_descriptor:

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

इस प्रकार, हम इसे स्वयं बना सकते हैं:

def find_all(a_str, sub):
    start = 0
    while True:
        start = a_str.find(sub, start)
        if start == -1: return
        yield start
        start += len(sub) # use start += 1 to find overlapping matches

list(find_all('spam spam spam spam', 'spam')) # [0, 5, 10, 15]

कोई अस्थायी तार या regexes की आवश्यकता नहीं है।


22
मैचों ओवरलैपिंग पाने के लिए, इसे बदलना पर्याप्त होना चाहिए start += len(sub)के साथ start += 1
कार्ल केनचेल

4
मेरा मानना ​​है कि आपकी पिछली टिप्पणी आपके उत्तर में एक पोस्टस्क्रिप्ट होनी चाहिए।
tzot

1
आपका कोड "GATATATGCATATACTT" में "ATAT" को खोजने के लिए काम नहीं करता है
आशीष नेगी

2
इसके अलावा मैंने जो टिप्पणी की है, उसे देखें। यह ओवरलैपिंग मैच का एक उदाहरण है।
कार्ल केनचेल

4
के व्यवहार से मेल खाने के लिए re.findall, मैं len(sub) or 1इसके बजाय जोड़ने की सलाह len(sub)दूंगा, अन्यथा यह जनरेटर कभी खाली स्थान पर समाप्त नहीं होगा।
WGH

45

यहां सभी प्राप्त करने का एक बहुत ही अक्षम तरीका है (यानी अतिव्यापी) मैच:

>>> string = "test test test test"
>>> [i for i in range(len(string)) if string.startswith('test', i)]
[0, 5, 10, 15]

25

फिर से, पुराने धागे, लेकिन यहाँ एक जनरेटर और सादे का उपयोग कर मेरा समाधान है str.find

def findall(p, s):
    '''Yields all the positions of
    the pattern p in the string s.'''
    i = s.find(p)
    while i != -1:
        yield i
        i = s.find(p, i+1)

उदाहरण

x = 'banananassantana'
[(i, x[i:i+2]) for i in findall('na', x)]

रिटर्न

[(2, 'na'), (4, 'na'), (6, 'na'), (14, 'na')]

3
यह सुंदर लग रहा है!
fabio.sang

21

आप re.finditer()गैर-अतिव्यापी मैचों के लिए उपयोग कर सकते हैं ।

>>> import re
>>> aString = 'this is a string where the substring "is" is repeated several times'
>>> print [(a.start(), a.end()) for a in list(re.finditer('is', aString))]
[(2, 4), (5, 7), (38, 40), (42, 44)]

लेकिन इसके लिए काम नहीं करेंगे :

In [1]: aString="ababa"

In [2]: print [(a.start(), a.end()) for a in list(re.finditer('aba', aString))]
Output: [(0, 3)]

12
क्यों एक सूची से बाहर एक सूची बनाते हैं, यह प्रक्रिया को धीमा कर देता है।
प्रद्युम्नसर

2
एस्ट्रिंग वीएस एस्ट्रिंग;)
नेक्सडी।

18

आइए, हम एक साथ पुनरावृत्ति करें।

def locations_of_substring(string, substring):
    """Return a list of locations of a substring."""

    substring_length = len(substring)    
    def recurse(locations_found, start):
        location = string.find(substring, start)
        if location != -1:
            return recurse(locations_found + [location], location+substring_length)
        else:
            return locations_found

    return recurse([], 0)

print(locations_of_substring('this is a test for finding this and this', 'this'))
# prints [0, 27, 36]

इस तरह से नियमित अभिव्यक्ति की कोई आवश्यकता नहीं है।


मुझे बस आश्चर्य हुआ "अजगर में एक स्ट्रिंग के अंदर एक विकल्प का पता लगाने के लिए एक फैंसी तरीका है" ... और फिर गुग्लिंग के 5 मिनट के बाद मुझे आपका कोड मिला। साझा करने के लिए धन्यवाद!!!
गिपाराडा

3
इस कोड में कई समस्याएं हैं। चूंकि यह ओपन-एंडेड डेटा पर जल्द ही काम कर रहा है या बाद में RecursionErrorयदि आप कई पर्याप्त घटनाएँ हैं तो आप इसमें टकराएँगे। एक और एक दो फेंक-दूर सूचियां हैं जो प्रत्येक तत्व पर केवल एक तत्व को जोड़ने के लिए बनाता है, जो एक स्ट्रिंग खोज फ़ंक्शन के लिए बहुत ही उप-प्रकार है, जिसे संभवतः बहुत बार कहा जा सकता है। यद्यपि कभी-कभी पुनरावर्ती कार्य सुरुचिपूर्ण और स्पष्ट लगते हैं, उन्हें सावधानी के साथ लिया जाना चाहिए।
इवान निकोलेव

11

यदि आप सिर्फ एक ही पात्र की तलाश में हैं, तो यह काम करेगा:

string = "dooobiedoobiedoobie"
match = 'o'
reduce(lambda count, char: count + 1 if char == match else count, string, 0)
# produces 7

इसके अलावा,

string = "test test test test"
match = "test"
len(string.split(match)) - 1
# produces 4

मेरा कूबड़ यह है कि इनमें से कोई भी (विशेष रूप से # 2) बहुत अच्छा नहीं है।


gr8 solution .. मैं .. विभाजन के उपयोग से प्रभावित हूँ ()
शांतनु पथक

9

यह एक पुराना धागा है लेकिन मुझे इसमें दिलचस्पी थी और मैं इसका समाधान साझा करना चाहता था।

def find_all(a_string, sub):
    result = []
    k = 0
    while k < len(a_string):
        k = a_string.find(sub, k)
        if k == -1:
            return result
        else:
            result.append(k)
            k += 1 #change to k += len(sub) to not search overlapping results
    return result

यह उन स्थानों की सूची लौटा देना चाहिए जहां सबस्ट्रिंग पाया गया था। कृपया देखें कि क्या आपको सुधार के लिए कोई त्रुटि या कमरा दिखाई देता है।


6

यह मेरे लिए re.finditer का उपयोग करके ट्रिक करता है

import re

text = 'This is sample text to test if this pythonic '\
       'program can serve as an indexing platform for '\
       'finding words in a paragraph. It can give '\
       'values as to where the word is located with the '\
       'different examples as stated'

#  find all occurances of the word 'as' in the above text

find_the_word = re.finditer('as', text)

for match in find_the_word:
    print('start {}, end {}, search string \'{}\''.
          format(match.start(), match.end(), match.group()))

5

यह धागा थोड़ा पुराना है लेकिन यह मेरे लिए काम कर रहा है:

numberString = "onetwothreefourfivesixseveneightninefiveten"
testString = "five"

marker = 0
while marker < len(numberString):
    try:
        print(numberString.index("five",marker))
        marker = numberString.index("five", marker) + 1
    except ValueError:
        print("String not found")
        marker = len(numberString)

5

तुम कोशिश कर सकते हो :

>>> string = "test test test test"
>>> for index,value in enumerate(string):
    if string[index:index+(len("test"))] == "test":
        print index

0
5
10
15

2

दूसरों द्वारा प्रदान किए गए समाधान पूरी तरह से उपलब्ध विधि खोजने () या किसी भी उपलब्ध तरीकों पर आधारित हैं।

एक स्ट्रिंग में एक सबस्टेशन के सभी घटनाओं को खोजने के लिए कोर बुनियादी एल्गोरिथ्म क्या है?

def find_all(string,substring):
    """
    Function: Returning all the index of substring in a string
    Arguments: String and the search string
    Return:Returning a list
    """
    length = len(substring)
    c=0
    indexes = []
    while c < len(string):
        if string[c:c+length] == substring:
            indexes.append(c)
        c=c+1
    return indexes

आप स्ट्रै क्लास को नए वर्ग में भी इनहेरिट कर सकते हैं और नीचे इस फ़ंक्शन का उपयोग कर सकते हैं।

class newstr(str):
def find_all(string,substring):
    """
    Function: Returning all the index of substring in a string
    Arguments: String and the search string
    Return:Returning a list
    """
    length = len(substring)
    c=0
    indexes = []
    while c < len(string):
        if string[c:c+length] == substring:
            indexes.append(c)
        c=c+1
    return indexes

विधि को बुला रहा है

newstr.find_all ('क्या आपको यह उत्तर सहायक लगता है? फिर इसे बढ़ाएँ!', 'यह')


2

यह फ़ंक्शन स्ट्रिंग के अंदर सभी पदों को नहीं देखता है, यह कंप्यूट संसाधनों को बर्बाद नहीं करता है। मेरी कोशिश:

def findAll(string,word):
    all_positions=[]
    next_pos=-1
    while True:
        next_pos=string.find(word,next_pos+1)
        if(next_pos<0):
            break
        all_positions.append(next_pos)
    return all_positions

इसका उपयोग करने के लिए इसे इस तरह से कॉल करें:

result=findAll('this word is a big word man how many words are there?','word')

1

जब किसी दस्तावेज़ में बड़ी मात्रा में शब्दों की तलाश होती है, तो फ्लैशटेक्स्ट का उपयोग करें

from flashtext import KeywordProcessor
words = ['test', 'exam', 'quiz']
txt = 'this is a test'
kwp = KeywordProcessor()
kwp.add_keywords_from_list(words)
result = kwp.extract_keywords(txt, span_info=True)

Flashtext खोज शब्दों की बड़ी सूची पर regex की तुलना में तेजी से चलता है।


0
src = input() # we will find substring in this string
sub = input() # substring

res = []
pos = src.find(sub)
while pos != -1:
    res.append(pos)
    pos = src.find(sub, pos + 1)

1
हालांकि यह कोड ओपी के मुद्दे को हल कर सकता है, लेकिन स्पष्टीकरण को शामिल करना सबसे अच्छा है कि आपका कोड ओपी के मुद्दे को कैसे संबोधित करता है। इस तरह, भविष्य के आगंतुक आपके पोस्ट से सीख सकते हैं, और इसे अपने स्वयं के कोड पर लागू कर सकते हैं। SO एक कोडिंग सेवा नहीं है, बल्कि ज्ञान के लिए एक संसाधन है। इसके अलावा, उच्च गुणवत्ता, पूर्ण उत्तरों के अपग्रेड होने की अधिक संभावना है। ये विशेषताएं, इस आवश्यकता के साथ कि सभी पद स्व-सम्‍मिलित हैं, एसओ की कुछ ताकतें एक मंच के रूप में हैं, जो इसे मंचों से अलग करती हैं। आप अतिरिक्त जानकारी जोड़ने और / या स्रोत प्रलेखन के साथ अपनी व्याख्याओं को पूरक करने के लिए संपादित कर सकते हैं
शेरलहोमन

0

यह हैकर्रानक के एक समान प्रश्न का समाधान है। मुझे उम्मीद है कि यह आपकी मदद कर सकता है।

import re
a = input()
b = input()
if b not in a:
    print((-1,-1))
else:
    #create two list as
    start_indc = [m.start() for m in re.finditer('(?=' + b + ')', a)]
    for i in range(len(start_indc)):
        print((start_indc[i], start_indc[i]+len(b)-1))

आउटपुट:

aaadaa
aa
(0, 1)
(1, 2)
(4, 5)

-1

स्लाइस करके हम सभी संयोजनों को संभव पाते हैं और उन्हें एक सूची में जोड़ते हैं और countफ़ंक्शन का उपयोग करते हुए कितनी बार पाते हैं

s=input()
n=len(s)
l=[]
f=input()
print(s[0])
for i in range(0,n):
    for j in range(1,n+1):
        l.append(s[i:j])
if f in l:
    print(l.count(f))

जब s="test test test test"और f="test"आपका कोड प्रिंट करता है 4, लेकिन ओपी को उम्मीद है[0,5,10,15]
बार्सन

एक शब्द के लिए लिखा है कोड को अद्यतन करेगा
BONTHA SREEVIDHYA

-2

कृपया नीचे दिए गए कोड को देखें

#!/usr/bin/env python
# coding:utf-8
'''黄哥Python'''


def get_substring_indices(text, s):
    result = [i for i in range(len(text)) if text.startswith(s, i)]
    return result


if __name__ == '__main__':
    text = "How much wood would a wood chuck chuck if a wood chuck could chuck wood?"
    s = 'wood'
    print get_substring_indices(text, s)

-2

पायथोनिक तरीका होगा:

mystring = 'Hello World, this should work!'
find_all = lambda c,s: [x for x in range(c.find(s), len(c)) if c[x] == s]

# s represents the search string
# c represents the character string

find_all(mystring,'o')    # will return all positions of 'o'

[4, 7, 20, 26] 
>>> 

3
1) यह एक सवाल कैसे मदद करता है जो 7 साल पहले उत्तर दिया गया था? 2) इस तरह से इस्तेमाल करना lambdaपाइथोनिक नहीं है और PEP8 के खिलाफ जाता है । 3) यह
ओपीएस

अजगर का मतलब यह नहीं है कि "अजगर की उतनी सुविधाओं का उपयोग करें जितना आप सोच सकते हैं"
klutt

-2

आप आसानी से उपयोग कर सकते हैं:

string.count('test')!

https://www.programiz.com/python-programming/methods/string/count

चीयर्स!


इसका उत्तर होना चाहिए
मैक्सवेल चैंडलर

8
स्ट्रिंग संख्या () विधि दिए गए स्ट्रिंग में एक स्ट्रिंग की घटनाओं की संख्या लौटाती है। उनकी लोकेशन नहीं।
एस्ट्रिड

5
यह सभी मामलों में संतोषजनक नहीं है, s = 'केला', उप = 'आना'। सब इस स्थिति में दो बार होता है लेकिन s.sub ('ana') 1 पर लौटेगा
जॉय डेनियल डार्को
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.