a

Câu hỏi Liệu Python có một chuỗi 'chứa' phương pháp chuỗi con?


Tôi đang tìm kiếm một string.contains hoặc là string.indexof trong Python.

Tôi muốn làm:

if not somestring.contains("blah"):
   continue

2885
2017-08-09 02:52


gốc




Các câu trả lời:


Bạn có thể dùng in nhà điều hành:

if "blah" not in somestring: 
    continue

4372
2017-08-09 02:56





Nếu đó chỉ là tìm kiếm chuỗi con bạn có thể sử dụng string.find("substring").

Bạn phải cẩn thận một chút với find, indexin mặc dù, vì chúng là các tìm kiếm chuỗi con. Nói cách khác, điều này:

s = "This be a string"
if s.find("is") == -1:
    print "No 'is' here!"
else:
    print "Found 'is' in the string."

Nó sẽ in Found 'is' in the string. Tương tự, if "is" in s: sẽ đánh giá True. Điều này có thể hoặc không thể là những gì bạn muốn.


460
2017-08-09 02:55



1 để làm nổi bật gotchas liên quan đến tìm kiếm chuỗi con. giải pháp rõ ràng là if ' is ' in s: sẽ trở lại False như (có thể) dự kiến. - aaronasterling
@aaronasterling Rõ ràng nó có thể, nhưng không hoàn toàn chính xác. Điều gì sẽ xảy ra nếu bạn có dấu chấm câu hoặc nó ở đầu hoặc cuối? Về viết hoa thì sao? Tốt hơn là tìm kiếm regex không phân biệt chữ hoa chữ thường \bis\b (ranh giới từ). - Bob
@JamieBull Một lần nữa, bạn phải xem xét nếu bạn muốn bao gồm dấu câu như một dấu phân cách cho một từ. Tách rời sẽ có tác dụng tương tự như giải pháp ngây thơ của việc kiểm tra ' is ', đáng chú ý là nó sẽ không bắt được This is, a comma' hoặc là 'It is.'. - Bob
@JamieBull: Tôi rất nghi ngờ bất kỳ sự phân chia đầu vào thực sự nào với s.split(string.punctuation + string.whitespace) sẽ chia đều một lần; split không giống như strip/rstrip/lstrip gia đình của các chức năng, nó chỉ chia tách khi nó nhìn thấy tất cả các ký tự dấu phân cách, liên tục, theo thứ tự chính xác đó. Nếu bạn muốn chia nhỏ các lớp nhân vật, bạn sẽ trở lại các biểu thức chính quy (tại thời điểm đó, tìm kiếm r'\bis\b' mà không tách là cách đơn giản, nhanh hơn để đi). - ShadowRanger
'is' not in (w.lower() for w in s.translate(string.maketrans(' ' * len(string.punctuation + string.whitespace), string.punctuation + string.whitespace)).split() - ok, lấy đi. Điều này bây giờ là vô lý ... - Jamie Bull


if needle in haystack: là cách sử dụng bình thường, như @Michael nói - nó dựa vào in toán tử, dễ đọc hơn và nhanh hơn gọi phương thức.

Nếu bạn thực sự cần một phương pháp thay vì một toán tử (ví dụ: để làm một số điều lạ key= cho một loại rất đặc biệt ...?), đó sẽ là 'haystack'.__contains__. Nhưng vì ví dụ của bạn là để sử dụng trong một if, Tôi đoán bạn không thực sự có nghĩa là những gì bạn nói ;-). Nó không phải là hình thức tốt (cũng không thể đọc được, cũng không hiệu quả) để sử dụng các phương thức đặc biệt trực tiếp - chúng được sử dụng, thay vào đó, thông qua các toán tử và nội trang ủy nhiệm cho chúng.


125
2017-08-09 03:19





Về cơ bản, bạn muốn tìm một chuỗi con trong một chuỗi trong python. Có hai cách để tìm kiếm chuỗi con trong chuỗi bằng Python.

Phương pháp 1: in nhà điều hành

Bạn có thể sử dụng Python in toán tử để kiểm tra chuỗi con. Nó khá đơn giản và trực quan. Nó sẽ trở lại True nếu chuỗi con được tìm thấy trong chuỗi khác False.

>>> "King" in "King's landing"
True

>>> "Jon Snow" in "King's landing"
False

Cách 2: str.find() phương pháp

Phương pháp thứ hai là sử dụng str.find() phương pháp. Ở đây, chúng tôi gọi .find() phương pháp trên chuỗi trong đó chuỗi con được tìm thấy. Chúng ta chuyển chuỗi con tới phương thức find () và kiểm tra giá trị trả về của nó. Nếu giá trị của nó khác -1, chuỗi con được tìm thấy trong chuỗi, nếu không thì không. Giá trị trả về là chỉ mục nơi chuỗi con được tìm thấy.

>>> some_string = "valar morghulis"

>>> some_string.find("morghulis")
6

>>> some_string.find("dohaeris")
-1

Tôi sẽ khuyên bạn nên sử dụng phương pháp đầu tiên vì nó là Pythonic và trực quan hơn.


98
2018-05-26 17:46





Liệu Python có một chuỗi chứa phương thức chuỗi con?

Có, nhưng Python có một toán tử so sánh mà bạn nên sử dụng thay vào đó, bởi vì ngôn ngữ dự định sử dụng nó, và các lập trình viên khác sẽ mong bạn sử dụng nó. Từ khóa đó là in, được sử dụng như một toán tử so sánh:

>>> 'foo' in '**foo**'
True

Ngược lại (bổ sung), mà câu hỏi ban đầu yêu cầu, là not in:

>>> 'foo' not in '**foo**' # returns False
False

Đây là ngữ nghĩa giống như not 'foo' in '**foo**' nhưng nó dễ đọc hơn và được cung cấp rõ ràng hơn trong ngôn ngữ như một sự cải thiện khả năng đọc.

Tránh sử dụng __contains__, findindex

Như đã hứa, đây là contains phương pháp:

str.__contains__('**foo**', 'foo')

trả về True. Bạn cũng có thể gọi hàm này từ thể hiện của siêu chuỗi:

'**foo**'.__contains__('foo')

Nhưng đừng. Các phương thức bắt đầu bằng dấu gạch dưới được coi là riêng tư về mặt ngữ nghĩa. Lý do duy nhất để sử dụng điều này là khi mở rộng in và not in chức năng (ví dụ: nếu phân lớp phụ str):

class NoisyString(str):
    def __contains__(self, other):
        print('testing if "{0}" in "{1}"'.format(other, self))
        return super(NoisyString, self).__contains__(other)

ns = NoisyString('a string with a substring inside')

và bây giờ:

>>> 'substring' in ns
testing if "substring" in "a string with a substring inside"
True

Ngoài ra, tránh các phương thức chuỗi sau:

>>> '**foo**'.index('foo')
2
>>> '**foo**'.find('foo')
2

>>> '**oo**'.find('foo')
-1
>>> '**oo**'.index('foo')

Traceback (most recent call last):
  File "<pyshell#40>", line 1, in <module>
    '**oo**'.index('foo')
ValueError: substring not found

Các ngôn ngữ khác có thể không có phương pháp để kiểm tra trực tiếp cho các chất nền, và vì vậy bạn sẽ phải sử dụng các kiểu phương thức này, nhưng với Python, nó sẽ hiệu quả hơn nhiều khi sử dụng intoán tử so sánh.

So sánh hiệu suất

Chúng ta có thể so sánh nhiều cách khác nhau để hoàn thành cùng một mục tiêu.

import timeit

def in_(s, other):
    return other in s

def contains(s, other):
    return s.__contains__(other)

def find(s, other):
    return s.find(other) != -1

def index(s, other):
    try:
        s.index(other)
    except ValueError:
        return False
    else:
        return True



perf_dict = {
'in:True': min(timeit.repeat(lambda: in_('superstring', 'str'))),
'in:False': min(timeit.repeat(lambda: in_('superstring', 'not'))),
'__contains__:True': min(timeit.repeat(lambda: contains('superstring', 'str'))),
'__contains__:False': min(timeit.repeat(lambda: contains('superstring', 'not'))),
'find:True': min(timeit.repeat(lambda: find('superstring', 'str'))),
'find:False': min(timeit.repeat(lambda: find('superstring', 'not'))),
'index:True': min(timeit.repeat(lambda: index('superstring', 'str'))),
'index:False': min(timeit.repeat(lambda: index('superstring', 'not'))),
}

Và bây giờ chúng ta thấy rằng việc sử dụng in nhanh hơn nhiều so với những người khác. Ít thời gian để thực hiện một thao tác tương đương tốt hơn:

>>> perf_dict
{'in:True': 0.16450627865128808,
 'in:False': 0.1609668098178645,
 '__contains__:True': 0.24355481654697542,
 '__contains__:False': 0.24382793854783813,
 'find:True': 0.3067379407923454,
 'find:False': 0.29860888058124146,
 'index:True': 0.29647137792585454,
 'index:False': 0.5502287584545229}

90
2017-11-25 22:33



Tại sao nên tránh str.index và str.find? Bạn có thể đề nghị người khác tìm thấy chỉ mục của chuỗi con thay vì chỉ cho dù nó tồn tại hay không? (hoặc bạn có nghĩa là tránh sử dụng chúng thay cho chứa - vì vậy không sử dụng s.find(ss) != -1 thay vì ss in s?) - coderforlife
Chính xác như vậy, mặc dù ý định đằng sau việc sử dụng các phương pháp đó có thể được giải quyết tốt hơn bằng cách sử dụng thanh lịch của re mô-đun. Tôi vẫn chưa tìm thấy cách sử dụng cho str.index hoặc str.find trong bất kỳ mã nào tôi đã viết. - Aaron Hall♦


Không, không có string.contains(str) phương pháp, nhưng có in nhà điều hành:

if substring in someString:
    print "It's there!!!"

Đây là một ví dụ làm việc phức tạp hơn:

# Print all files with dot in home directory
import commands
(st, output) = commands.getstatusoutput('ls -a ~')
print [f for f in output.split('\n') if '.' in f ]

61
2017-09-30 18:59



Không phải là người hâm mộ phân tích cú pháp ls, nhưng tôi hiểu tại sao bạn đưa ra ví dụ này. Vẫn ... sẽ thấy khá hơn os.walk. - Josh Detwiler


in Chuỗi và danh sách Python

Dưới đây là một số ví dụ hữu ích tự nói về in phương pháp:

"foo" in "foobar"
True

"foo" in "Foobar"
False

"foo" in "Foobar".lower()
True

"foo".capitalize() in "Foobar"
True

"foo" in ["bar", "foo", "foobar"]
True

"foo" in ["fo", "o", "foobar"]
False

Caveat. Danh sách có thể lặp lại và in phương thức hoạt động trên các vòng lặp, không chỉ các chuỗi.


31
2018-04-28 18:52



Danh sách có thể lặp lại được chuyển sang tìm kiếm bất kỳ danh sách nào trong một chuỗi không? Ví dụ: ["bar", "foo", "foobar"] in "foof"? - CaffeinatedCoder
@CaffeinatedCoder, không, điều này đòi hỏi lặp lồng nhau. Thực hiện tốt nhất bằng cách nối danh sách với các đường ống "|" .join (["bar", "foo", "foobar"]) và biên dịch regex ra khỏi nó, sau đó khớp với "foof" - firelynx
Tôi đã tìm ra sớm rằng nó cũng có thể được thực hiện với một máy phát điện, cho phép tôi tránh regex. Cảm ơn bạn đã thay thế! - CaffeinatedCoder
bất kỳ ([x in "foof" cho x trong ["bar", "foo", "foobar"]]) - Izaak Weiss
@IzaakWeiss Một lớp lót của bạn hoạt động, nhưng nó không phải là rất dễ đọc, và nó lặp lồng nhau. Tôi sẽ khuyên không nên làm điều này - firelynx