Soru Python'un 'içerir' bir alt dizgi yöntemi var mı?


Bir bakıyorum string.contains veya string.indexof Python'da yöntem.

Ben yapmak istiyorum:

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

2885
2017-08-09 02:52


Menşei




Cevaplar:


Kullanabilirsiniz in Şebeke:

if "blah" not in somestring: 
    continue

4372
2017-08-09 02:56





Sadece bir alt dize araması varsa string.find("substring").

Biraz dikkatli olmalısın find, index, ve in olsa da, alt dizin aramaları gibi. Başka bir deyişle, bu:

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

Yazdırır Found 'is' in the string. Benzer şekilde, if "is" in s: değerlendirir True. Bu senin istediğin gibi olabilir ya da olmayabilir.


460
2017-08-09 02:55



Alt dizin aramalarında yer alan gotcha'ların vurgulanması için +1. bariz çözüm if ' is ' in s: dönecek False (muhtemelen) beklendiği gibi. - aaronasterling
@ aaronasterling Açıkçası, ama tamamen doğru değil. Noktalama işaretiniz varsa veya başlangıç ​​veya bitişte ne varsa? Büyük harf nedir? Daha iyi bir durum duyarsız normal ifade aranması \bis\b (sözcük sınırları). - Bob
@JamieBull Bir kez daha, noktalama işaretini bir kelime için sınırlayıcı olarak eklemek isteyip istemediğinizi düşünmelisiniz. Bölünme büyük ölçüde kontrol için naif çözüm olarak aynı etkiye sahip olurdu ' is 'özellikle dikkat çekmeyecek This is, a comma' veya 'It is.'. - Bob
@JamieBull: Benimle herhangi bir gerçek girdinin bölünmesinden şüphe duyuyorum. s.split(string.punctuation + string.whitespace) bir kez bile bölünür; split gibi değil strip/rstrip/lstrip işlev ailesi, yalnızca sınırlayıcı olarak tüm sınırlayıcı karakterleri tam olarak sırayla gördüğünde böler. Karakter sınıflarına bölünmek istiyorsanız, normal ifadelere geri dönersiniz ( r'\bis\b' bölmeksizin daha basit, daha hızlı bir yoldur). - ShadowRanger
'is' not in (w.lower() for w in s.translate(string.maketrans(' ' * len(string.punctuation + string.whitespace), string.punctuation + string.whitespace)).split() - Tamam, alınan nokta. Bu çok saçma ... - Jamie Bull


if needle in haystack: @Michael'ın dediği gibi normal kullanımdır - in Operatör, bir yöntem çağrısı daha okunabilir ve daha hızlı.

Bir operatör yerine gerçekten bir yönteme ihtiyacınız varsa (ör. Bazı garip şeyler yapmak için) key= çok tuhaf bir tür ...?) 'haystack'.__contains__. Ancak, örneğiniz bir ifSanırım ne dediğini kastetmiyorsun ;-). Doğrudan özel yöntemler kullanmak için iyi bir form (ne okunabilir, ne de verimli) değil - bunun yerine, onları temsil eden operatörler ve yerleşikler aracılığıyla kullanılmaları gerekir.


125
2017-08-09 03:19





Temel olarak, bir dizede python'da bir alt dizgi bulmak istersiniz. Python'da bir dizede bir alt dizeyi aramak için iki yol vardır.

Yöntem 1: in Şebeke

Python’u in alt dizgiyi denetlemek için operatör. Oldukça basit ve sezgisel. Geri dönecek True Alt dizede başka dizede bulunursa False.

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

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

Yöntem 2: str.find() yöntem

İkinci yöntem, str.find() yöntem. İşte biz .find() Alt dizenin bulunacağı dizede yöntem. Alt dizeyi find () yöntemine iletir ve dönüş değerini kontrol ederiz. Değeri -1'den farklıysa, alt dizgede dizgede bulundu, aksi halde değil. Döndürülen değer, alt dizenin bulunduğu dizindir.

>>> some_string = "valar morghulis"

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

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

Daha fazla Pythonic ve sezgisel olduğu için ilk yöntemi kullanmanızı tavsiye ederim.


98
2018-05-26 17:46





Python'da bir dize alt dizgi yöntemi var mı?

Evet, fakat Python'un yerine kullanmanız gereken bir karşılaştırma operatörü vardır, çünkü dil kullanımını amaçlamaktadır ve diğer programcılar bunu kullanmayı bekler. Bu anahtar kelime inkarşılaştırma operatörü olarak kullanılır:

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

Orijinal soruyu soran (tamamlayıcı), not in:

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

Bu semantik olarak aynı not 'foo' in '**foo**' ancak okunabilirlik ve açıkça okunabilirlik olarak dilde sağlanmıştır.

Kullanmaktan kaçın __contains__, find, ve index

Söz verildiği gibi, işte contains yöntem:

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

döner True. Ayrıca, bu işlevi süper kullanıcı örneğinden de çağırabilirsiniz:

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

Ama yapma. Alt çizgilerle başlayan yöntemler, anlamsal olarak özel kabul edilir. Bunu kullanmanın tek nedeni, in ve not in işlevsellik (örneğin alt sınıflarsa) 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')

ve şimdi:

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

Ayrıca, aşağıdaki dize yöntemlerinden kaçının:

>>> '**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

Diğer diller, alt dizeleri doğrudan sınamak için hiçbir yönteme sahip olmayabilir ve bu nedenle, bu tür yöntemleri kullanmanız gerekir, ancak Python ile, kullanmak çok daha etkilidir. inkarşılaştırma operatörü.

Performans karşılaştırmaları

Aynı amacı gerçekleştirmenin çeşitli yollarını karşılaştırabiliriz.

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'))),
}

Ve şimdi bunu görüyoruz in diğerlerinden çok daha hızlıdır. Eşdeğer bir işlem yapmak için daha az zaman daha iyidir:

>>> 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



Neden kaçının str.index ve str.find? Başka birinin, var olup olmadığını değil, bir alt dizinin dizinini nasıl bulmasını önerirsiniz? (ya da bunları içeren bir yerde kullanmaktan kaçınmak mı demek istediniz - kullanma s.find(ss) != -1 yerine ss in s?) - coderforlife
Kesinlikle, bu yöntemlerin kullanımının arkasındaki amaç, re modülü. Henüz yazdığım herhangi bir kodda str.index veya str.find için henüz bir kullanım bulamadım. - Aaron Hall♦


Hayır, hiç yok string.contains(str) yöntem, ama var in Şebeke:

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

İşte daha karmaşık bir çalışma örneği:

# 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



Ayrıştırma hayranı değil lsama neden bu örneği verdin. Yine de ... os.walk. - Josh Detwiler


in Python dizeleri ve listeleri

Burada kendileriyle ilgili olarak konuşan birkaç yararlı örnek var. in yöntem:

"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

Uyarı. Listeler yinelenebilir ve in yöntem sadece dizeleri değil, yineleyiciler üzerinde hareket eder.


31
2018-04-28 18:52



Listenin herhangi birisini tek bir dizede aramak için tekrar tekrar çevrilebilir mi? Ör: ["bar", "foo", "foobar"] in "foof"? - CaffeinatedCoder
@CaffeinatedCoder, hayır, bu iç içe yineleme gerektirir. En iyi "|" ("bar", "foo", "foobar"]) boruları ile listeye katılarak ve bunun dışında bir regexin derlenmesiyle, ardından "foof" ile eşleştirerek yapılır - firelynx
Erken bir şekilde, bir jeneratörle yapılabileceğini anladım ve bu da düzenli ifadelerden kaçınmamı sağladı. Yine de bir alternatif için teşekkürler! - CaffeinatedCoder
[[bar], "foo", "foobar"]] 'da x için herhangi bir ([x in "foof")]) - Izaak Weiss
@IzaakWeiss Bir liner çalışır, ancak çok okunabilir değil ve iç içe yineleme yapar. Bunu yapmamaya karşı tavsiye ederim - firelynx


Görünüşe göre, vektörel karşılaştırma için benzer bir şey yoktur. Bunu yapmak için açık bir Python yolu şöyle olurdu:

names = ['bob', 'john', 'mike']
any(st in 'bob and john' for st in names) 
>> True

any(st in 'mary and jane' for st in names) 
>> False

21
2017-07-17 13:19



Çünkü atomik değişkenlerden bir Ürün yaratmanın bajillion yolları vardır. Bunları bir tuple, bir liste (Kartezyen Ürünlerin formları olan ve zımni bir siparişle birlikte gelir) ya da bir sınıfın (önsel düzende olmayan) veya sözlük değerlerinin özellikleri olarak adlandırılabilir ya da dosyalar olabilirsiniz. bir dizin ya da her neyse. Bir 'kapsayıcı' veya 'bağlam' içinde bir şeyi benzersiz bir şekilde tanımlayabildiğinizde (iter veya getitem), 'kapsayıcıyı bir çeşit vektör olarak görebilir ve üzerinde ikili opları tanımlayabilirsiniz. en.wikipedia.org/wiki/... - Niriel
@Ufos sanırım bunu yapmak için daha açık python yolu kullanmaktır any() veya all(). Sevmek : any([st in 'bob and john' for st in names]) >>> True - mgc
@mgc, değiştirdi any, Teşekkürler. - Ufos
İç köşeli parantezlere ihtiyacınız yok - python.org/dev/peps/pep-0289 - Eamonn M.R.