पायथन में एक स्ट्रिंग के भीतर एक स्ट्रिंग की कई घटनाओं का पता लगाना


81

मैं पायथन में एक स्ट्रिंग के भीतर एक स्ट्रिंग की कई घटनाएं कैसे पा सकता हूं? इस पर विचार करो:

>>> text = "Allowed Hello Hollow"
>>> text.find("ll")
1
>>> 

तो पहली घटना llउम्मीद के मुताबिक 1 पर है। मुझे इसकी अगली घटना कैसे पता चलेगी?

समान प्रश्न सूची के लिए मान्य है। विचार करें:

>>> x = ['ll', 'ok', 'll']

मैं llउनकी अनुक्रमणिका के साथ सभी कैसे ढूँढ सकता हूँ ?


3
>>> text.count ("ll")
ब्लैकपी

3
@blackappy इस घटना को घटित करता है, उन्हें स्थानीय नहीं करता है
pcko1

जवाबों:


123

नियमित अभिव्यक्ति का उपयोग करते हुए, आप re.finditerसभी (गैर-अतिव्यापी) घटनाओं को खोजने के लिए उपयोग कर सकते हैं :

>>> import re
>>> text = 'Allowed Hello Hollow'
>>> for m in re.finditer('ll', text):
         print('ll found', m.start(), m.end())

ll found 1 3
ll found 10 12
ll found 16 18

वैकल्पिक रूप से, यदि आप नियमित अभिव्यक्तियों के ओवरहेड नहीं चाहते हैं, तो आप अगले इंडेक्स str.findप्राप्त करने के लिए बार-बार उपयोग कर सकते हैं :

>>> text = 'Allowed Hello Hollow'
>>> index = 0
>>> while index < len(text):
        index = text.find('ll', index)
        if index == -1:
            break
        print('ll found at', index)
        index += 2 # +2 because len('ll') == 2

ll found at  1
ll found at  10
ll found at  16

यह सूचियों और अन्य दृश्यों के लिए भी काम करता है।


1
क्या नियमित अभिव्यक्ति का उपयोग किए बिना इसे करने का कोई तरीका नहीं है?
user225312

1
ऐसा नहीं है कि मुझे कोई समस्या है, लेकिन सिर्फ उत्सुक।
14:

2
सूची नहीं है find। लेकिन यह indexआपके साथ काम करता है , आपको बस except ValueErrorइसके लिए परीक्षण करने की आवश्यकता है -1
aaronasterling

@ ऐरन: मैं मूल विचार की बात कर रहा था, बेशक आपको सूचियों के लिए इसे थोड़ा संशोधित करना होगा (उदाहरण के लिए index += 1)।
प्रहार करें

4
अब जब आप पूरी index += 2बात का उल्लेख करते हैं , यदि आप इसे स्ट्रिंग 'lllll' पर लागू करते हैं, तो यह 'll' की चार घटनाओं में से दो को याद करेगा। index += 1स्ट्रिंग के लिए भी सबसे अच्छा है।
एरोनस्टरलिंग

31

मुझे लगता है कि तुम जो खोज रहे हो वह है string.count

"Allowed Hello Hollow".count('ll')
>>> 3

आशा है कि यह
नोट करने में मदद करता है : यह केवल गैर-अतिव्यापी घटनाओं को पकड़ता है


वाह धन्यवाद। यह एक बहुत ही सरल काम था
डेरिक

यह एक स्ट्रिंग में दिए गए घटनों की संख्या की गणना करने के लिए एक उत्तर है , न कि इस वास्तविक प्रश्न के लिए जो मैचों की अनुक्रमितों को खोजने के लिए कहता है, न कि उनकी गिनती ...
Tomerikoo

26

सूची उदाहरण के लिए, एक समझ का उपयोग करें:

>>> l = ['ll', 'xx', 'll']
>>> print [n for (n, e) in enumerate(l) if e == 'll']
[0, 2]

इसी तरह तार के लिए:

>>> text = "Allowed Hello Hollow"
>>> print [n for n in xrange(len(text)) if text.find('ll', n) == n]
[1, 10, 16]

यह "ll" के समीपवर्ती रन को सूचीबद्ध करेगा, जो आप चाहते हैं या नहीं हो सकता है:

>>> text = 'Alllowed Hello Holllow'
>>> print [n for n in xrange(len(text)) if text.find('ll', n) == n]
[1, 2, 11, 17, 18]

वाह मुझे यह पसंद है। धन्यवाद। यह पूर्ण है।
user225312

5
यह बेहद अक्षम है।
क्लेमेंट

1
@ क्लेमेंट एक अधिक कुशल उदाहरण पोस्ट करता है
3

@ क्लेमेंट प्रिंट [n for xrange (len (टेक्स्ट)) में यदि टेक्स्ट [n-1: n] == 'll']
स्टीफन

मेरा मतलब था: प्रिंट [n in n के लिए xrange (len (टेक्स्ट)) यदि टेक्स्ट [n: n + 2] == 'll']
स्टीफन

14

एफडब्ल्यूआईडब्ल्यू, यहां गैर-आरई विकल्प के एक जोड़े हैं जो मुझे लगता है कि पोक के समाधान की तुलना में शून्य हैं

इसके लिए पहला प्रयोग str.indexऔर जाँच ValueError:

def findall(sub, string):
    """
    >>> text = "Allowed Hello Hollow"
    >>> tuple(findall('ll', text))
    (1, 10, 16)
    """
    index = 0 - len(sub)
    try:
        while True:
            index = string.index(sub, index + len(sub))
            yield index
    except ValueError:
        pass

दूसरा परीक्षण का उपयोग करके str.findप्रहरी के लिए उपयोग करता है और जाँच करता है :-1iter

def findall_iter(sub, string):
    """
    >>> text = "Allowed Hello Hollow"
    >>> tuple(findall_iter('ll', text))
    (1, 10, 16)
    """
    def next_index(length):
        index = 0 - length
        while True:
            index = string.find(sub, index + length)
            yield index
    return iter(next_index(len(sub)).next, -1)

इनमें से किसी भी कार्य को सूची में, टपल या अन्य चलने योग्य तार पर लागू करने के लिए , आप एक उच्च-स्तरीय फ़ंक्शन का उपयोग कर सकते हैं - जो किसी फ़ंक्शन को उसके तर्कों के रूप में लेता है - जैसे यह

def findall_each(findall, sub, strings):
    """
    >>> texts = ("fail", "dolly the llama", "Hello", "Hollow", "not ok")
    >>> list(findall_each(findall, 'll', texts))
    [(), (2, 10), (2,), (2,), ()]
    >>> texts = ("parallellized", "illegally", "dillydallying", "hillbillies")
    >>> list(findall_each(findall_iter, 'll', texts))
    [(4, 7), (1, 6), (2, 7), (2, 6)]
    """
    return (tuple(findall(sub, string)) for string in strings)

3

अपनी सूची उदाहरण के लिए:

In [1]: x = ['ll','ok','ll']

In [2]: for idx, value in enumerate(x):
   ...:     if value == 'll':
   ...:         print idx, value       
0 ll
2 ll

यदि आप एक सूची में सभी आइटम चाहते थे जिसमें 'll' शामिल था, तो आप ऐसा भी कर सकते हैं।

In [3]: x = ['Allowed','Hello','World','Hollow']

In [4]: for idx, value in enumerate(x):
   ...:     if 'll' in value:
   ...:         print idx, value
   ...:         
   ...:         
0 Allowed
1 Hello
3 Hollow

2
>>> for n,c in enumerate(text):
...   try:
...     if c+text[n+1] == "ll": print n
...   except: pass
...
1
10
16

1

सामान्य रूप से प्रोग्रामिंग के लिए नया और एक ऑनलाइन ट्यूटोरियल के माध्यम से काम करना। मुझे भी ऐसा करने के लिए कहा गया था, लेकिन केवल उन तरीकों का उपयोग करके जो मैंने अब तक सीखे थे (मूल रूप से तार और छोर)। यकीन नहीं है कि अगर यह यहाँ कोई मूल्य जोड़ता है, और मुझे पता है कि यह नहीं है कि आप इसे कैसे करेंगे, लेकिन मुझे इसके साथ काम करने के लिए मिला:

needle = input()
haystack = input()
counter = 0
n=-1
for i in range (n+1,len(haystack)+1):
   for j in range(n+1,len(haystack)+1):
      n=-1
      if needle != haystack[i:j]:
         n = n+1
         continue
      if needle == haystack[i:j]:
         counter = counter + 1
print (counter)

1

यह संस्करण स्ट्रिंग की लंबाई में रैखिक होना चाहिए, और ठीक होना चाहिए जब तक कि अनुक्रम बहुत दोहराव नहीं होते हैं (जिस स्थिति में आप थोड़ी देर लूप के साथ पुनरावृत्ति को बदल सकते हैं)।

def find_all(st, substr, start_pos=0, accum=[]):
    ix = st.find(substr, start_pos)
    if ix == -1:
        return accum
    return find_all(st, substr, start_pos=ix + 1, accum=accum + [ix])

bstpierre की लिस्ट कॉम्प्रिहेंशन, शॉर्ट सीक्वेंस के लिए एक अच्छा समाधान है, लेकिन द्विघात जटिलता को देखता है और कभी भी मेरे द्वारा उपयोग किए जा रहे लंबे टेक्स्ट पर समाप्त नहीं होता है।

findall_lc = lambda txt, substr: [n for n in xrange(len(txt))
                                   if txt.find(substr, n) == n]

गैर-तुच्छ लंबाई की एक यादृच्छिक स्ट्रिंग के लिए, दो कार्य समान परिणाम देते हैं:

import random, string; random.seed(0)
s = ''.join([random.choice(string.ascii_lowercase) for _ in range(100000)])

>>> find_all(s, 'th') == findall_lc(s, 'th')
True
>>> findall_lc(s, 'th')[:4]
[564, 818, 1872, 2470]

लेकिन द्विघात संस्करण लगभग 300 गुना धीमा है

%timeit find_all(s, 'th')
1000 loops, best of 3: 282 µs per loop

%timeit findall_lc(s, 'th')    
10 loops, best of 3: 92.3 ms per loop

0
#!/usr/local/bin python3
#-*- coding: utf-8 -*-

main_string = input()
sub_string = input()

count = counter = 0

for i in range(len(main_string)):
    if main_string[i] == sub_string[0]:
        k = i + 1
        for j in range(1, len(sub_string)):
            if k != len(main_string) and main_string[k] == sub_string[j]:
                count += 1
                k += 1
        if count == (len(sub_string) - 1):
            counter += 1
        count = 0

print(counter) 

यह कार्यक्रम सभी सबस्ट्रिंग की संख्या की गणना करता है, भले ही वे रेगेक्स के उपयोग के बिना ओवरलैप किए गए हों। लेकिन यह एक अनुभवहीन कार्यान्वयन है और सबसे खराब स्थिति में बेहतर परिणामों के लिए इसे प्रत्यय ट्री, केएमपी और अन्य स्ट्रिंग मिलान डेटा संरचनाओं और एल्गोरिदम के माध्यम से जाने की सलाह दी जाती है।


0

यहाँ कई घटनाओं को खोजने के लिए मेरा कार्य है। अन्य समाधानों के विपरीत, यह स्लाइसिंग के लिए वैकल्पिक आरंभ और अंत मापदंडों का समर्थन करता है, जैसे str.index:

def all_substring_indexes(string, substring, start=0, end=None):
    result = []
    new_start = start
    while True:
        try:
            index = string.index(substring, new_start, end)
        except ValueError:
            return result
        else:
            result.append(index)
            new_start = index + len(substring)

0

एक साधारण पुनरावृत्ति कोड जो सूचकांकों की एक सूची लौटाता है जहां प्रतिस्थापन होता है।

        def allindices(string, sub):
           l=[]
           i = string.find(sub)
           while i >= 0:
              l.append(i)
              i = string.find(sub, i + 1)
           return l

0

आप सापेक्ष पदों को प्राप्त करने के लिए विभाजित कर सकते हैं फिर एक सूची में लगातार संख्याओं को जोड़ सकते हैं और वांछित स्ट्रिंग इंडेक्स प्राप्त करने के लिए एक ही समय में (स्ट्रिंग लंबाई * घटना क्रम) जोड़ सकते हैं।

>>> key = 'll'
>>> text = "Allowed Hello Hollow"
>>> x = [len(i) for i in text.split(key)[:-1]]
>>> [sum(x[:i+1]) + i*len(key) for i in range(len(x))]
[1, 10, 16]
>>> 

0

शायद पाइथोनिक नहीं है, लेकिन कुछ हद तक आत्म-व्याख्यात्मक। यह मूल स्ट्रिंग में देखे गए शब्द की स्थिति देता है।

def retrieve_occurences(sequence, word, result, base_counter):
     indx = sequence.find(word)
     if indx == -1:
         return result
     result.append(indx + base_counter)
     base_counter += indx + len(word)
     return retrieve_occurences(sequence[indx + len(word):], word, result, base_counter)

0

मुझे लगता है कि पाठ की लंबाई के लिए परीक्षण करने की कोई आवश्यकता नहीं है; बस तब तक ढूंढते रहिए जब तक कि खोजने के लिए कुछ न बचा हो। ऐशे ही:

    >>> text = 'Allowed Hello Hollow'
    >>> place = 0
    >>> while text.find('ll', place) != -1:
            print('ll found at', text.find('ll', place))
            place = text.find('ll', place) + 2


    ll found at 1
    ll found at 10
    ll found at 16

0

आप इसे सशर्त सूची समझ के साथ भी कर सकते हैं:

string1= "Allowed Hello Hollow"
string2= "ll"
print [num for num in xrange(len(string1)-len(string2)+1) if string1[num:num+len(string2)]==string2]
# [1, 10, 16]

0

मुझे कुछ समय पहले ही यह विचार आया था। स्ट्रिंग स्प्लिंग और स्ट्रिंग खोज के साथ एक लूप का उपयोग करना स्ट्रिंग को ओवरलैप करने के लिए भी काम कर सकता है।

findin = "algorithm alma mater alison alternation alpines"
search = "al"
inx = 0
num_str = 0

while True:
    inx = findin.find(search)
    if inx == -1: #breaks before adding 1 to number of string
        break
    inx = inx + 1
    findin = findin[inx:] #to splice the 'unsearched' part of the string
    num_str = num_str + 1 #counts no. of string

if num_str != 0:
    print("There are ",num_str," ",search," in your string.")
else:
    print("There are no ",search," in your string.")

मैं पायथन प्रोग्रामिंग (किसी भी भाषा का प्रोग्रामिंग, वास्तव में) में एक शौकिया हूं, और मुझे यकीन नहीं है कि अन्य मुद्दे क्या हो सकते हैं, लेकिन मुझे लगता है कि यह ठीक काम कर रहा है?

मुझे लगता है कि कम () का उपयोग कहीं और किया जा सकता है, यदि आवश्यक हो तो भी।


0

निम्नलिखित फ़ंक्शन स्थिति के बारे में सूचित करते हुए एक स्ट्रिंग के सभी घटनाओं को दूसरे स्थान पर पाता है जहां प्रत्येक घटना पाई जाती है।

आप नीचे दी गई तालिका में परीक्षण मामलों का उपयोग करके फ़ंक्शन को कॉल कर सकते हैं। आप शब्दों, रिक्त स्थान और संख्याओं के साथ मिश्रित प्रयास कर सकते हैं।

ओवरलैपिंग वर्णों के साथ फ़ंक्शन अच्छी तरह से काम करता है।

|         theString          | aString |
| -------------------------- | ------- |
| "661444444423666455678966" |  "55"   |
| "661444444423666455678966" |  "44"   |
| "6123666455678966"         |  "666"  |
| "66123666455678966"        |  "66"   |

Calling examples:
1. print("Number of occurrences: ", find_all("123666455556785555966", "5555"))
   
   output:
           Found in position:  7
           Found in position:  14
           Number of occurrences:  2
   
2. print("Number of occorrences: ", find_all("Allowed Hello Hollow", "ll "))

   output:
          Found in position:  1
          Found in position:  10
          Found in position:  16
          Number of occurrences:  3

3. print("Number of occorrences: ", find_all("Aaa bbbcd$#@@abWebbrbbbbrr 123", "bbb"))

   output:
         Found in position:  4
         Found in position:  21
         Number of occurrences:  2
         

def find_all(theString, aString):
    count = 0
    i = len(aString)
    x = 0

    while x < len(theString) - (i-1): 
        if theString[x:x+i] == aString:        
            print("Found in position: ", x)
            x=x+i
            count=count+1
        else:
            x=x+1
    return count
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.