2012-06-20 31 views
32

Tôi có một số mã đơn giản:python - tìm char trong chuỗi - tôi có thể lấy tất cả các chỉ mục không?

def find(str, ch): 
    for ltr in str: 
     if ltr == ch: 
      return str.index(ltr) 
find("ooottat", "o") 

Chức năng chỉ trả lại chỉ số đầu tiên. Nếu tôi thay đổi trở lại để in, nó sẽ in 0 0 0. Tại sao điều này và có cách nào để có được 0 1 2?

+6

Chỉ cần nói, không sử dụng str làm tên biến vì nó là từ khóa hiện tại bằng Python. –

+1

@ sr2222: 'str' không phải là từ khóa, nó chỉ là tên được tạo sẵn (từ khóa không thể sử dụng làm tên biến) – geoffspear

+1

@Wooble Đủ công bằng. Không thay đổi thực tế là sử dụng nó như một tên biến là thực hành xấu. :) –

Trả lời

65

Điều này là do str.index(ch) sẽ trả về chỉ mục tại đó ch xảy ra lần đầu tiên. Hãy thử:

def find(s, ch): 
    return [i for i, ltr in enumerate(s) if ltr == ch] 

Điều này sẽ trả về danh sách tất cả các chỉ mục bạn cần.

P.S. Câu trả lời của Hugh cho thấy một chức năng máy phát điện (nó tạo ra sự khác biệt nếu danh sách các chỉ mục có thể nhận được lớn). Chức năng này cũng có thể được điều chỉnh bằng cách thay đổi [] thành ().

+0

Sử dụng 'liệt kê', giải pháp tốt đẹp! – lmichelbacher

+0

ch phải là một ký tự đơn? Tôi đã thử nó bằng cách sử dụng 'ch = '& #'' và 's = Н а р о д' và điều đó không hiệu quả. –

+0

@ChrisNielsen thực sự, điều này sẽ không hoạt động đối với các phần tử dài hơn vì 'liệt kê' lặp lại các ký tự trong' s' và do đó 'ltr == ch' chỉ có thể là' True' nếu 'ch' là một ký tự đơn. –

7
def find_offsets(haystack, needle): 
    """ 
    Find the start of all (possibly-overlapping) instances of needle in haystack 
    """ 
    offs = -1 
    while True: 
     offs = haystack.find(needle, offs+1) 
     if offs == -1: 
      break 
     else: 
      yield offs 

for offs in find_offsets("ooottat", "o"): 
    print offs 

kết quả trong

0 
1 
2 
5

Lev's answer là người tôi muốn sử dụng, tuy nhiên đây là một cái gì đó dựa trên mã ban đầu của bạn:

def find(str, ch): 
    for i, ltr in enumerate(str): 
     if ltr == ch: 
      yield i 

>>> list(find("ooottat", "o")) 
[0, 1, 2] 
15

tôi sẽ đi với Lev, nhưng nó có giá trị chỉ ra rằng nếu bạn kết thúc với các tìm kiếm phức tạp hơn bằng cách sử dụng re.finditer có thể đáng ghi nhớ (nhưng lại thường gây ra nhiều rắc rối hơn giá trị - nhưng đôi khi hữu ích để biết)

test = "ooottat" 
[ (i.start(), i.end()) for i in re.finditer('o', test)] 
# [(0, 1), (1, 2), (2, 3)] 

[ (i.start(), i.end()) for i in re.finditer('o+', test)] 
# [(0, 3)] 
0

Bạn có thể thử này

def find(ch,string1): 
    for i in range(len(string1)): 
     if ch == string1[i]: 
      pos.append(i)   
-1

Rất nhiều lựa chọn thay thế bằng biểu thức thông thường

import re 

iter = re.finditer(r'o', searchString) 

indexes = [x.start() for x in iter] 

Indexes là danh sách các chỉ số chuỗi các trận đấu

0

Sử dụng gấu trúc chúng ta có thể làm được điều này và trả lại một dict với tất cả các chỉ số, phiên bản đơn giản:

import pandas as pd 

d = (pd.Series(l) 
    .reset_index() 
    .groupby(0)['index'] 
    .apply(list) 
    .to_dict()) 

Nhưng chúng tôi cũng có thể xây dựng trong điều kiện, ví dụ: chỉ khi hai hoặc nhiều lần xuất hiện:

d = (pd.Series(l) 
    .reset_index() 
    .groupby(0)['index'] 
    .apply(lambda x: list(x) if len(list(x)) > 1 else None) 
    .dropna() 
    .to_dict()) 
Các vấn đề liên quan