Bir dizgede öncü dizilimin uzunluğu nasıl bulunur?

Bir dizgideki baştaki boşlukların sayısını saymak isterim. Bunu yapmanın en Pythonic yolu nedir?

>>>F(' ' * 5 + 'a')
5

(güncelleme) İşte birkaç cevabın zamanlamaları:

import timeit
>>> timeit.timeit("s.index(re.search(r'\S',s).group())", number=10000, setup="import re;s='     a'")
0.027384042739868164
>>> timeit.timeit("len([i for i in itertools.takewhile(str.isspace,s)])", number=10000, setup="import itertools;s='     a'")
0.025166034698486328
>>> timeit.timeit("next(idx for idx,val in enumerate(s) if val != ' ')", number=10000, setup="s='     a'")
0.028306961059570312
>>> timeit.timeit("F('     a')", number=10000, setup="def F(s): return len(s)-len(s.lstrip(' '))")
0.0051808357238769531
3
@AvinashRaj Lider alanları sayıyor
katma yazar Bhargav Rao, kaynak
Bence SİZ'in cevabı en Pythonic, sanırım Saksham Varma yaklaşıyor. YMMV. Önerilen çeşitli alternatifler üzerinde bazı timeit testleri yapmanın iyi olacağını düşünüyorum ... BTW, bir işlev adı için F gibi bir büyük harf kullanarak kesinlikle değil Pythonic. :)
katma yazar PM 2Ring, kaynak

10 cevap

Using re module

>>> s
'     a'
>>> import re
>>> s.index(re.search(r'\S',s).group())
5

Using itertools

>>> import itertools
>>> len([i for i in itertools.takewhile(str.isspace,s)])
5

Kaba kuvvet yolu

>>> def F(s):
...     for i in s:
...          if i!=' ':
...               return s.index(i)
... 
>>> F(s)
5
7
katma
>>> F = lambda x:len(x)-len(x.lstrip(' '))
>>> F(' ' * 5 + 'a')
5

Önde gelen boşlukların uzunluğunu bulmanız gerekirse, şimdi yalnızca boşluklarla sınırlı olan lstrip'ten '' işaretini kaldırabilirsiniz.

4
katma
Lambayı kullanmadıysanız, ancak yukarıda gösterildiği gibi iki uzunluk arasındaki fark en hızlı sonucu veriyor gibi görünüyor.
katma yazar Mark Harrison, kaynak

s dizgisini tekrarlamak için numaralandır öğesini kullanın. s öğesinde '' olmayan bir öğeye bastığınızda, aradığınızı bu dizini yazdırın.

>>> for i, val in enumerate(s):
...    if val != ' ':  
...       print i  
...       break
...
5
3
katma
def f(string):
    try:
        return [c == ' ' for c in string].index(False)
    except ValueError:
        return -1

looks for the first character that doesn't match ' '

2
katma
@ PM2Ring İyi puanlar, cevabı güncelledi.
katma yazar Huey, kaynak
Güzel. , ValueError hariç: adsız bir yan tümce kullanmaktan çok daha iyidir. docs.python.org/3/tutorial/errors.html#handling adresinden -exceptions "Son istisna maddesi, bir joker karakter görevi görmek için istisna adlarını çıkartabilir. Bunu, çok dikkatli kullanın, çünkü bu şekilde gerçek bir programlama hatasını maskelemek kolaydır!". Ayrıca bkz: stackoverflow.com/questions/14797375/… ifadeleri hariç
katma yazar PM 2Ring, kaynak

yeterince açık olmadığım için üzgünüm .... bir sayacı başlat ... sadece dizgiyi yinele ve listedeki her değişkenin bir beyaz boşluk ile sayacının 1'er artışla ...

counter = 0

sstring = " " * 5 + "a"

for x in sstring:

    if x == " ":
        counter += 1
    else:
        continue

print(counter)

İçtenlikle özür dilerim, senaryomun neden bu berbat formatta gösterildiğini sürekli olarak bilmiyorum .. Ben burada yeniyim

2
katma
@Samlexxy diğer blokta kırmanız gerekir. Bunu f = "" * 5 + "a" + "b" gibi bir dize için çalıştırmayı deneyin ve göreceksiniz.
katma yazar mu 無, kaynak
Lütfen cevabınıza biraz daha ayrıntı ekler misiniz?
katma yazar abarisone, kaynak
Kodunuz bir dizgede önde gelen boşlukları bulamıyor, bir dizgede toplam boşluk sayısını bulur, bu da sum (ch in s (s) için ch) ile kolaydır.
katma yazar Adam Smith, kaynak
Python için değilim . Kodunuzu sstring = 'a bc' ile deneyin. 3 'ı yazdırır, dizgede yalnızca bir tane öncü boşluk olduğundan 1 ' u yazdırmalıdır.
katma yazar PM 2Ring, kaynak
Hala devam etmeme -> ara vermeyi düzelttiniz. Ayrıca, test verileriniz yetersiz.
katma yazar PM 2Ring, kaynak
Yanlışlıkla sözdiziminde ve/veya mantıkta basit bir hata yaparsanız, yanıt olarak göndermeden önce kodu test etmek her zaman iyi bir fikirdir.
katma yazar PM 2Ring, kaynak
Bu kod çalışmıyor. Eğer x == "": , değil f == "" ise test etmelisiniz. Ancak o zaman bile, yalnızca önde gelen boşlukları değil f içindeki tüm boşlukları sayar. Ve açıklamanız gerektiği gibi devam et 'i break olarak değiştirmeniz gerektiğini düzeltmek için.
katma yazar PM 2Ring, kaynak
üzgünüm ... lemme tercümanımı kullanarak kodu çalıştırmayı dene
katma yazar samlexxy, kaynak
sanırım doğru python için yenisin ve "devam et" ile "ara" statatement arasındaki farkı bilmiyorsun .... soruyu bir kez daha okuyun .... başında beyaz boşluk saymak için bir komut dosyası bir dize ..... ayrıca anlamadıysanız "else: devam" ifadesini de ihmal edebilirsiniz.
katma yazar samlexxy, kaynak
dize ile yineleme .. yineleme yapıldıktan sonra program otomatik olarak kendini kırar .... belki de senin açıklama anladım
katma yazar samlexxy, kaynak
dostum sorduğum kodu tamamladım ... ilk 5 boşluk olan .... senin örneğinle devam etmelisin ki senin gibi "mola" olmalı inanıyorum .... ve mai programının yazarın örneğine bağlı olduğunu söylediğim gibi evrensel değil
katma yazar samlexxy, kaynak
umarım bu iyidir
katma yazar samlexxy, kaynak
nedeni bu oldu ..... ben bunu değiştirebildim ..... sadece çok az değişiklik gerektirdi
katma yazar samlexxy, kaynak

re modülü aracılığıyla. ve len işlevini kullanarak.

>>> s = '     a'
>>> len(re.sub(r'\S.*', '',s))
5

Bu, tüm karakterleri ilk boşluk olmayan karakterden en son karaktere kadar kaldırır. Ardından len işlevi, baştaki boşlukların uzunluğunu veren sonuç dizgisine uygulanır.

VEYA

>>> s = '     a'
>>> len(re.match(r'\s*', s).group())
5
>>> s = 'a'
>>> len(re.match(r'\s*', s).group())
0

Bu sadece sıfır veya daha fazla önde gelen boşlukla eşleşir.

VEYA

Re.match işlevini end() kullanın özelliği.

>>> s = '     a'
>>> re.match(r'\s*', s).end()
5
>>> re.match(r'\s*', 'd').end()
0

Adam'a Teşekkürler

1
katma

Ooh bir tane daha henüz kimsenin göndermediği.

def leading_spaces(s):
    return next(idx for idx,val in enumerate(s) if val != " ")

Bu neredeyse kesinlikle bunu yapmanın en hızlı yoludur

1
katma
Neden Ooh bir tane daha ile başlayan bir cevap
katma yazar Bhargav Rao, kaynak

Basit bir harita ve sonra toplamı:

>>> sum(map(bool, takewhile(str.isspace, '    a  ')))
4
0
katma

İlk karakteri kullanarak dizgiyi sol tarafa soyun:

>>> s = 'aaaaabaca'
>>> len(s) - len(s.lstrip(s[0]))
5

Boş dizeler için çalışmasını istiyorsanız, sadece bir çek ekleyin:

>>> s = ''
>>> len(s) - len(s.lstrip(s[0])) if s else 0
0
0
katma

Kod:

>>> i = 0
>>> while i < len(s):
...     if s[i] != ' ':
...       print i
...       break  
...     i += 1

5
0
katma
@martineau düzeltti.
katma yazar neo, kaynak