Возьмите пробел / отступ строки с помощью Python - PullRequest
12 голосов
/ 15 февраля 2010

В принципе, если у меня есть строка текста, которая начинается с отступа, каков наилучший способ получить этот отступ и поместить его в переменную в Python? Например, если строка:

\t\tthis line has two tabs of indention

Тогда он вернул бы '\ t \ t'. Или, если строка была:

    this line has four spaces of indention

Тогда будет возвращено четыре пробела.

Так что, я думаю, вы могли бы сказать, что мне просто нужно удалить все, начиная от строки, начиная с первого непробельного символа и заканчивая концом. Мысли?

Ответы [ 6 ]

24 голосов
/ 15 февраля 2010
import re
s = "\t\tthis line has two tabs of indention"
re.match(r"\s*", s).group()
// "\t\t"
s = "    this line has four spaces of indention"
re.match(r"\s*", s).group()
// "    "

А для удаления ведущих пробелов используйте lstrip .


Поскольку есть отрицательные голоса, вероятно, ставящие под сомнение эффективность регулярных выражений, я провел некоторое профилирование, чтобы проверить эффективность каждого случая.

Очень длинная строка, очень короткое начальное пространство

RegEx> Itertools >> lstrip

>>> timeit.timeit('r.match(s).group()', 'import re;r=re.compile(r"\s*")s="          hello world!"*10000', number=100000)
0.10037684440612793
>>> timeit.timeit('"".join(itertools.takewhile(lambda x:x.isspace(),s))', 'import itertools;s="          hello world!"*10000', number=100000)
0.7092740535736084
>>> timeit.timeit('"".join(itertools.takewhile(str.isspace,s))', 'import itertools;s="          hello world!"*10000', number=100000)
0.51730513572692871
>>> timeit.timeit('s[:-len(s.lstrip())]', 's="          hello world!"*10000', number=100000)
2.6478431224822998

Очень короткая строка, очень короткое начальное пространство

lstrip> RegEx> Itertools

Если вы можете ограничить длину строки тысячами символов или меньше, трюк с полосой может быть лучше.

>>> timeit.timeit('r.match(s).group()', 'import re;r=re.compile(r"\s*");s="          hello world!"*100', number=100000)
0.099548101425170898
>>> timeit.timeit('"".join(itertools.takewhile(str.isspace,s))', 'import itertools;s="          hello world!"*100', number=100000)
0.53602385520935059
>>> timeit.timeit('s[:-len(s.lstrip())]', 's="          hello world!"*100', number=100000)
0.064291000366210938

Это показывает, что трюк lstrip масштабируется примерно как O (√n), а методы RegEx и itertool - O (1), если число ведущих пробелов не много.

Очень короткая строка, очень длинный начальный пробел

lstrip >> RegEx >>> Itertools

Если много пробелов, не используйте RegEx.

>>> timeit.timeit('s[:-len(s.lstrip())]', 's=" "*2000', number=10000)
0.047424077987670898
>>> timeit.timeit('r.match(s).group()', 'import re;r=re.compile(r"\s*");s=" "*2000', number=10000)
0.2433168888092041
>>> timeit.timeit('"".join(itertools.takewhile(str.isspace,s))', 'import itertools;s=" "*2000', number=10000)
3.9949162006378174

Очень длинная строка, очень длинный начальный пробел

lstrip >>> RegEx >>>>>>>> Itertools

>>> timeit.timeit('s[:-len(s.lstrip())]', 's=" "*200000', number=10000)
4.2374031543731689
>>> timeit.timeit('r.match(s).group()', 'import re;r=re.compile(r"\s*");s=" "*200000', number=10000)
23.877214908599854
>>> timeit.timeit('"".join(itertools.takewhile(str.isspace,s))', 'import itertools;s=" "*200000', number=100)*100
415.72158336639404

Это показывает, что все методы масштабируются примерно как O (m), если непустая часть невелика.

12 голосов
/ 15 февраля 2010

Подлый путь: оскорбление lstrip!

fullstr = "\t\tthis line has two tabs of indentation"
startwhites = fullstr[:len(fullstr)-len(fullstr.lstrip())]

Таким образом, вам не нужно прорабатывать все детали пробелов!

(спасибо Адаму за исправление)

4 голосов
/ 15 февраля 2010

Это также можно сделать с str.isspace и itertools.takewhile вместо регулярных выражений.

import itertools

tests=['\t\tthis line has two tabs of indention',
       '    this line has four spaces of indention']

def indention(astr):
    # Using itertools.takewhile is efficient -- the looping stops immediately after the first
    # non-space character.
    return ''.join(itertools.takewhile(str.isspace,astr))

for test_string in tests:
    print(indention(test_string))
0 голосов
/ 15 февраля 2010
def whites(a):
return a[0:a.find(a.strip())]

В основном моя идея такова:

  1. Найдите полосу стартовой линии
  2. Найти разницу между стартовой линией и лишенной
0 голосов
/ 15 февраля 2010

Если вы заинтересованы в использовании регулярных выражений, вы можете использовать это. /\s/ обычно соответствует одному пробелу, поэтому /^\s+/ будет соответствовать пробелу, начинающему строку.

0 голосов
/ 15 февраля 2010

Как насчет использования регулярного выражения \s*, которое соответствует любым пробельным символам. Вам нужен только пробел в начале строки, поэтому либо search с регулярным выражением ^\s*, либо просто match с \s*.

...