Возврат наименьшего индекса для первого непробельного символа в строке в Python

Какой самый короткий способ сделать это в Python?

string = "   xyz"

должен вернуть индекс = 3


person Pablo    schedule 04.03.2010    source источник
comment
Почти дубликат: stackoverflow.com /вопросы/2268532/   -  person Ioannis Filippidis    schedule 11.09.2017


Ответы (7)


>>> next(i for i, j in enumerate('   xyz') if j.strip())
3

or

>>> next(i for i, j in enumerate('   xyz') if j not in string.whitespace)
3

в версиях Python ‹ 2.5 вам нужно будет сделать:

(...).next()
person SilentGhost    schedule 04.03.2010
comment
blah.strip() и blah.isspace() нормально работают с Unicode; string.whitespace застыл в прошлом веке. - person John Machin; 04.03.2010
comment
@Джон: говорит кто? Я вижу string.whitespace вторым наиболее эффективным подходом после общепринятого. - person SilentGhost; 04.03.2010
comment
Перечитайте мой комментарий. Я говорю о работе с Unicode; ни слова об эффективности. - person John Machin; 04.03.2010

Похоже, бригада «регулярные выражения могут все» взяли выходной, так что я заполню:

>>> tests = [u'foo', u' foo', u'\xA0foo']
>>> import re
>>> for test in tests:
...     print len(re.match(r"\s*", test, re.UNICODE).group(0))
...
0
1
1
>>>

FWIW: затраченное время равно O(the_answer), а не O(len(input_string))

person John Machin    schedule 04.03.2010

Многие из предыдущих решений повторяются в нескольких точках предлагаемых решений. А некоторые делают копии данных (строки). re.match(), strip(), enumerate(), isspace() дублируют работу за сценой.

next(idx for idx, chr in enumerate(string) if not chr.isspace())
next(idx for idx, chr in enumerate(string) if not chr.whitespace)

являются хорошим выбором для проверки строк на соответствие различным ведущим типам пробелов, таким как вертикальные табуляции и тому подобное, но это также увеличивает затраты.

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

def get_indent(astr):

    """Return index of first non-space character of a sequence else False."""

    try:
        iter(astr)
    except:
        raise

    # OR for not raising exceptions at all
    # if hasattr(astr,'__getitem__): return False

    idx = 0
    while idx < len(astr) and astr[idx] == ' ':
        idx += 1
    if astr[0] <> ' ':
        return False
    return idx

Хотя это может быть не самым быстрым или простым визуально, некоторые преимущества этого решения заключаются в том, что вы можете легко перенести его на другие языки и версии Python. И, вероятно, его легче всего отлаживать, так как в нем мало волшебного поведения. Если вы поместите суть функции в строку с вашим кодом, а не в функцию, вы удалите часть вызова функции и сделаете это решение похожим по байтовому коду на другие решения.

Кроме того, это решение допускает больше вариаций. Например, добавление теста для вкладок

or astr[idx] == '\t':

Или вы можете проверить все данные как итерируемые один раз вместо того, чтобы проверять, является ли каждая строка итерируемой. Помните, что такие вещи, как ""[0] вызывают исключение, а ""[0:] - нет.

Если вы хотите внедрить решение в строку, вы можете пойти по маршруту, отличному от Python:

i = 0
while i < len(s) and s[i] == ' ': i += 1

print i
3

. .

person DevPlayer    schedule 28.11.2012

person    schedule
comment
Если s длинный, а префикс пробела короткий, могут быть предпочтительнее другие решения (те, которые не делают временную почти копию s, получают ее длину, а затем отбрасывают временный объект). - person John Machin; 05.03.2010
comment
Строки @JohnMachin неизменяемы в Python, поэтому я очень сомневаюсь, что интерпретатор делает копию для strip(). Исходную строку можно просто использовать повторно с другой начальной позицией. - person bernie; 03.09.2020

person    schedule
comment
Убедитесь, что ваш код ничего не делает изящно. - приписывается Джону Бентли IIRC. - person John Machin; 04.03.2010
comment
Простите мне мое невежество, но кто он? - person Pablo; 04.03.2010
comment
Невежество простительно; другое дело нежелание пользоваться поисковиком ;-) en.wikipedia.org/wiki/Jon_Bentley - person John Machin; 04.03.2010
comment
@JohnMachin - D'oh ... хорошее замечание по поводу + вместо *. Мои мыслительные способности не были полностью включены этим утром. - person D.Shawley; 04.03.2010
comment
Также у вас есть лишние скобки. - person John Machin; 04.03.2010

person    schedule
comment
-1, так как это не удается для любой строки, состоящей из пробелов... StopIteration: в этом случае выводится ошибка - person kmonsoor; 14.02.2014

person    schedule
comment
-1, так как это не работает для любой строки, состоящей только из пробелов... :( ValueError: False отсутствует в списке - person kmonsoor; 14.02.2014