Her şeyi a'dan önce nasıl elde edebilirim: Python dizesinde


107

Bir dizedeki tüm harfleri a'dan önce almanın bir yolunu arıyorum: ama nereden başlayacağım konusunda hiçbir fikrim yok. Normal ifadeyi kullanır mıyım? Öyleyse nasıl?

string = "Username: How are you today?"

Birisi bana ne yapabileceğim konusunda bir örnek gösterebilir mi?

Yanıtlar:


181

Sadece splitişlevi kullanın . Bir liste döndürür, böylece ilk öğeyi tutabilirsiniz:

>>> s1.split(':')
['Username', ' How are you today?']
>>> s1.split(':')[0]
'Username'

12
Bölmeyi sınırlayın veya bu durumdas1.partition(':')[0]
Jon Clements'i

Teşekkürler, bu çok faydalı ve bilgilendiriciydi. Ayrıca çok yardımcı oldu, teşekkürler!
0Cool

2
Bölme kullanmayın, çünkü tüm ':' işlenir ve tam bir dizi oluşturur, daha uzun dizeler için iyi değildir. @ Hackaholic'in bir dizin kullanma yaklaşımına bakın. Sadece bu, aynı zamanda açıkça etkili olmayan bir normal ifade önermektedir. Ayrıca, indeks tabanlı .substringBefore () 'nin standart işlemini yapmak için bir python seçeneği olması gerekir. Ayrıca .substringBeforeLast (), vb. Gibi varyasyonlar kolaylık sağlamak için orada olmalıdır (kod tekrarlanmamalıdır). Bölümle ilgili noktayı fark ettim - evet, ':' işaretinden sonra daha az işlem var, ancak yine de '1' yerine <class 'tuple'>: ('1', ':', '2: 3') döndürüyor.
arntg

48

Kullanarak index:

>>> string = "Username: How are you today?"
>>> string[:string.index(":")]
'Username'

İndeks size :dizedeki konumunu verir , sonra onu dilimleyebilirsiniz.

Normal ifadeyi kullanmak istiyorsanız:

>>> import re
>>> re.match("(.*?):",string).group()
'Username'                       

match dizenin başından itibaren eşleşir.

Ayrıca kullanabilirsin itertools.takewhile

>>> import itertools
>>> "".join(itertools.takewhile(lambda x: x!=":", string))
'Username'

3
Bu yöntem (string [: string.index (":")]) muhtemelen bölünmeden daha temizdir
Damien

Hız için regex kullanmayın - burada bahsedilen ilk indeks seçeneğini kullanın. Regex açıkça o kadar etkili değil. Ayrıca, indeks tabanlı .substringBefore () 'nin standart işlemini yapmak için bir python seçeneği olması gerekir. Ayrıca .substringBeforeLast (), vb. Gibi varyasyonlar kolaylık sağlamak için orada olmalıdır (kod tekrarlanmamalıdır). Dizinin neden daha iyi çalıştığını açıklamak için bu yanıtı güncellemenizi ve ardından bunun fredtantini'nin yanıtında şu anda daha yüksek oylananlar da dahil olmak üzere diğer yaklaşımlara göre neden kullanılması gerektiğini açıklayın.
arntg

Mevcut değilse, dizin başarısız olur.
Marc

19

Buna gerek yok regexbunun için

>>> s = "Username: How are you today?"

Karakter splitdizisini bölmek için yöntemi kullanabilirsiniz.':'

>>> s.split(':')
['Username', ' How are you today?']

Ve [0]dizenin ilk bölümünü elde etmek için öğeyi dilimleyin

>>> s.split(':')[0]
'Username'

10

Bu çeşitli teknikleri Python 3.7.0 (IPython) altında karşılaştırdım.

TLDR

  • en hızlı (bölünme sembolü cbilindiğinde): önceden derlenmiş normal ifade.
  • (Aksi) en hızlı: s.partition(c)[0].
  • güvenli (yani, ne zaman cbulunmayabilir s): bölümleme, bölme.
  • güvensiz: dizin, normal ifade.

Kod

import string, random, re

SYMBOLS = string.ascii_uppercase + string.digits
SIZE = 100

def create_test_set(string_length):
    for _ in range(SIZE):
        random_string = ''.join(random.choices(SYMBOLS, k=string_length))
        yield (random.choice(random_string), random_string)

for string_length in (2**4, 2**8, 2**16, 2**32):
    print("\nString length:", string_length)
    print("  regex (compiled):", end=" ")
    test_set_for_regex = ((re.compile("(.*?)" + c).match, s) for (c, s) in test_set)
    %timeit [re_match(s).group() for (re_match, s) in test_set_for_regex]
    test_set = list(create_test_set(16))
    print("  partition:       ", end=" ")
    %timeit [s.partition(c)[0] for (c, s) in test_set]
    print("  index:           ", end=" ")
    %timeit [s[:s.index(c)] for (c, s) in test_set]
    print("  split (limited): ", end=" ")
    %timeit [s.split(c, 1)[0] for (c, s) in test_set]
    print("  split:           ", end=" ")
    %timeit [s.split(c)[0] for (c, s) in test_set]
    print("  regex:           ", end=" ")
    %timeit [re.match("(.*?)" + c, s).group() for (c, s) in test_set]

Sonuçlar

String length: 16
  regex (compiled): 156 ns ± 4.41 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
  partition:        19.3 µs ± 430 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
  index:            26.1 µs ± 341 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  split (limited):  26.8 µs ± 1.26 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  split:            26.3 µs ± 835 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  regex:            128 µs ± 4.02 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

String length: 256
  regex (compiled): 167 ns ± 2.7 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
  partition:        20.9 µs ± 694 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  index:            28.6 µs ± 2.73 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  split (limited):  27.4 µs ± 979 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  split:            31.5 µs ± 4.86 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  regex:            148 µs ± 7.05 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

String length: 65536
  regex (compiled): 173 ns ± 3.95 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
  partition:        20.9 µs ± 613 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
  index:            27.7 µs ± 515 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  split (limited):  27.2 µs ± 796 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  split:            26.5 µs ± 377 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  regex:            128 µs ± 1.5 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

String length: 4294967296
  regex (compiled): 165 ns ± 1.2 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
  partition:        19.9 µs ± 144 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
  index:            27.7 µs ± 571 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  split (limited):  26.1 µs ± 472 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  split:            28.1 µs ± 1.69 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
  regex:            137 µs ± 6.53 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

1
neden dizinin güvenli olmadığını düşünüyorsunuz?
James

3
s.index(c)ciçinde olmadığında bir Değer Hatası oluşturur s. Bu yüzden, bölümlenecek dizenin ayırıcı içerdiğinden emin olduğumda, aksi takdirde güvensiz olduğunu düşünürüm.
Aristide

1
İndeks için c, s içindedir, dolayısıyla güvenli değildir ve yine de en hızlısıdır.
arntg

3

partition () , sınırlayıcınız veya daha fazla sınırlayıcınızın olmadığı durumlar için daha iyi tahmin edilebilir sonuçlara sahip olduğundan, bu amaç için split () 'den daha iyi olabilir.


1
Her ikisi de partitionve splitboş bir dizeyle veya sınırlayıcı olmadan şeffaf bir şekilde çalışır. Her word[:word.index(':')]iki durumda da ortaya çıkacağını belirtmekte fayda var .
Rob Hall
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.