Возьмите строку пробел / отступ с Python

Хотя это можно взломать с помощью регулярного выражения (и мне нравится злоупотреблять регулярными выражениями так же, как и следующий парень), вы рано или поздно столкнетесь с проблемой обработки подстрок без более продвинутого синтаксического анализатора. Возможные способы попадания в проблему включают смешанные кавычки и экранированные кавычки.

Эта функция разделяет строку на запятую, но не те запятые, которые находятся внутри строки с одним или двумя кавычками. Его можно легко расширить с помощью дополнительных символов для использования в качестве кавычек (хотя для пар символов, таких как «», потребуется еще несколько строк кода), и даже скажет вам, если вы забыли закрыть цитату в своих данных:

function splitNotStrings(str){
  var parse=[], inString=false, escape=0, end=0

  for(var i=0, c; c=str[i]; i++){ // looping over the characters in str
    if(c==='\\'){ escape^=1; continue} // 1 when odd number of consecutive \
    if(c===','){
      if(!inString){
        parse.push(str.slice(end, i))
        end=i+1
      }
    }
    else if(splitNotStrings.quotes.indexOf(c)>-1 && !escape){
      if(c===inString) inString=false
      else if(!inString) inString=c
    }
    escape=0
  }
  // now we finished parsing, strings should be closed
  if(inString) throw SyntaxError('expected matching '+inString)
  if(end<i) parse.push(str.slice(end, i))
  return parse
}

splitNotStrings.quotes="'\"" // add other (symmetrical) quotes here
13
задан Charles Merriam 2 September 2010 в 00:20
поделиться

6 ответов

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

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

>>> 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), если непробельная часть не является много.

25
ответ дан 1 December 2019 в 19:23
поделиться

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

-2
ответ дан 1 December 2019 в 19:23
поделиться

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

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

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

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

12
ответ дан 1 December 2019 в 19:23
поделиться

Можно создать собственный EXE-файл, который содержит два других EXE-файла в качестве встроенных ресурсов и извлекает и выполняет каждый из них.

Убедитесь, что встраиваемый EXE может не работать, если извлечь его в другой каталог.

-121--2471821-

Нет, вам придется захватить значение переменной экземпляра вне лямбды, если вы хотите, чтобы она была вычислена в это конкретное время.

Это не отличается от того, как если бы вы написали это:

public void SetCashOnHand(int x) {
    this.cashOnHand = x;
    undoStack.Push(UndoSetCashOnHand);
}

private void UndoSetCashOnHand()
{
    this.setCashOnHand(this.cashOnHand);
}

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

Люди обычно обходят это, используя параметризованную функцию и сохраняя значение, которое передается функции как часть стека. Однако если вы хотите использовать функцию parameter- меньше , вам придется захватить ее в локальной системе.

-121--3383520-

Это также можно сделать с помощью str.isspace и itertools.takewhile вместо regex.

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))
4
ответ дан 1 December 2019 в 19:23
поделиться

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

-2
ответ дан 1 December 2019 в 19:23
поделиться
def whites(a):
return a[0:a.find(a.strip())]

По сути, моя идея такова:

  1. Найти полоску стартовой линии
  2. Найти разницу между стартовой линией и отрезанной
-1
ответ дан 1 December 2019 в 19:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: