2016-03-09 6 views
3

У меня есть строка, такая как manipulate widgets add,1,2,3 (извините, но я не могу изменить формат).удалить первые X слова и разделители строки - с несколькими разделителями

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

Давайте возьмем 3 в качестве примера, таким образом, удаляя manipulate widgets add и оставляя ,1,2,3

Или возьмите manipulate,widgets,add,1,2,3 удалить два слова (manipulate,widgets) и оставить ,add,1,2,3

Я могу разделить строку в список с words = re.split('[' + delimiters + ']',inputString.strip()), но я не может просто удалить кулак X слова

, скажем,

for i in range(1, numWorsdToRemove): 
      del words[0] 

, а затем return ' '.join(words), потому что это дает мне 1 2 3 4.

Как это сделать и сохранить исходные разделители неиспользуемых слов?

Чтобы сделать его интересным, строка ввода может содержать несколько пробелов или вкладок между словами; только одна запятая, но это также может иметь пробелы перед/SUC-ceeding его:

manipulate ,widgets add , 1, 2 , 3

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


[Update] Я принял «Kasramvd решение, но потом обнаружил, что это не правильно обрабатывать remover('LET FOUR = 2 + 2', 2) или remover('A -1 B text.txt', 2), так что теперь я предлагаю abounty.


[Обновить ++] разделители - это пробел, табуляция и запятая. Все остальное (в том числе знак равенства, знак минус и т. Д.) Является частью слова (хотя я был бы рад, если бы ответчики рассказывали мне, как добавить новый разделитель в будущем, если он станет необходимым)

+1

Что вы считаете разделители и что вы считаете слово? –

+0

разделители - это пробел и табуляция. Все остальное является частью слова (хотя я был бы счастлив, если бы ответчики рассказывали мне, как добавить новый разделитель в будущем, если он станет необходимым) – Mawg

+2

Вы по-прежнему обрабатываете запятые как разделители во втором случае: 'манипулировать, виджеты, add, 1,2,3' -> ', add, 1,2,3'. Первая и вторая запятые рассматриваются как разделители. – roadrunner66

ответ

2

Вы можете определить REGEX как этот

>>> import re 
>>> regEx = re.compile(r'(\s*,?\s*)') 

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

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

Например,

>>> def splitter(data, count): 
...  return "".join(re.split(regEx, data)[count + (count - 1):]) 
... 
>>> splitter("manipulate,widgets,add,1,2,3", 2) 
',add,1,2,3' 
>>> splitter("manipulate widgets add,1,2,3", 3) 
',1,2,3' 
1

Как насчет следующего подхода:

from itertools import islice 
import re 

text = "manipulate widgets,. add,1,2,3" 

for x in islice(re.finditer(r'\b(\w+?)\b', text), 2, 3): 
    print text[x.end():] 

Это будет дисплей:

,1,2,3   
2
s1='manipulate widgets add,1,2,3' 
# output desired ',1,2,3' 
s2='manipulate,widgets,add,1,2,3' 
# delete two words (manipulate,widgets) and leave ,add,1,2,3 
s3='manipulate ,widgets  add , 1, 2 , 3' 
# delete 2 or 3 words 

import re 

# for illustration 
print re.findall('\w+',s1) 
print re.findall('\w+',s2) 
print re.findall('\w+',s3) 
print 


def deletewords(s,n): 
    a= re.findall('\w+',s) 
    return ','.join(a[n:]) 

# examples for use  
print deletewords(s1,1) 
print deletewords(s2,2)  
print deletewords(s3,3) 

выход:

['manipulate', 'widgets', 'add', '1', '2', '3'] 
['manipulate', 'widgets', 'add', '1', '2', '3'] 
['manipulate', 'widgets', 'add', '1', '2', '3'] 

widgets,add,1,2,3 
add,1,2,3 
1,2,3 
1

Вы можете просто использовать re.sub():

>>> def remover(s, n): 
...  return re.sub(r'^(\s?\b\w+\b\s?){%s}'%n,'', s) 

DEMO:

>>> remover(s,3) 
',1,2,3' 
>>> remover(s,2) 
'add,1,2,3' 
>>> remover(s,1) 
'widgets add,1,2,3' 
>>> remover(s,0) 
'manipulate widgets add,1,2,3' 
+0

это не работает для строки 'LET FOUR = 2 + 2', когда я прошу удалить первые 3 слова :-( – Mawg

+0

И не работает, если в строке' AB -1 C есть отрицательное число '(обратите внимание, что знак минус не является копировальным аппаратом) при использовании в месте, где нужно вырезать EG' remove ('A -1 B text.txt', 2) ' – Mawg

0

Трудно сказать наверняка, что ваше определение "ограничителем" и "слово" есть. Например, в случае A -1 B text.txt, если -1 следует рассматривать как слово, или если строка обрабатывается так, как если бы не осталось слов для удаления. Это легко адаптируется к регулярному выражению, которое предоставил Kasramvd. Например, если вы считаете, -1 "слово", то это в основном делает трюк:

import re 


def remover(s, n): 
    return re.sub(r'^(\s?\s*[^\s]+\s?){%s}' % n, '', s) 

s = 'manipulate widgets add,1,2,3' 

print('\nString is: {}\n'.format(s)) 
[print('Remove {}: '.format(x), remover(s, x)) for x in range(4)] 

s = 'LET FOUR = 2 + 2 ' 

print('\nString is: {}\n', s) 
[print('Remove {}: '.format(x), remover(s, x)) for x in range(7)] 

s = 'A -1 B C text.txt' 

print('\nString is: {}\n', s) 
[print('Remove {}: '.format(x), remover(s, x)) for x in range(6)] 

, который производит:

String is: manipulate widgets add,1,2,3 

Remove 0: manipulate widgets add,1,2,3 
Remove 1: widgets add,1,2,3 
Remove 2: add,1,2,3 
Remove 3: 

String is: {} 
LET FOUR = 2 + 2 
Remove 0: LET FOUR = 2 + 2 
Remove 1: FOUR = 2 + 2 
Remove 2: = 2 + 2 
Remove 3: 2 + 2 
Remove 4: + 2 
Remove 5: 2 
Remove 6: 

String is: {} 
A -1 B C text.txt 
Remove 0: A -1 B C text.txt 
Remove 1: -1 B C text.txt 
Remove 2: B C text.txt 
Remove 3: C text.txt 
Remove 4: text.txt 
Remove 5: 

А как насчет =? Был ли = предполагаемым «словом» или «разделителем» или что? Если правила разные, сообщите нам, какие правила действительно существуют.

+0

разделители - это пробел и табуляция. Все остальное является частью слово (хотя я был бы счастлив, если бы ответчики сказали мне, как добавить новый разделитель в будущем, если он станет необходимым). LET X = 42' - это четыре слова. – Mawg

+1

Я обновил его, чтобы использовать пробелы в качестве разделителя. есть дополнительный разделитель, просто добавьте его в '[^ \ s]' часть регулярного выражения. Это в основном ищет символы, которые не являются пробелами. –

1

@начальный постер. Пожалуйста, отредактируйте тестовые примеры, поскольку некоторые из ваших заявлений кажутся противоречивыми. Второй тестовый пример рассматривает запятую как разделитель. Но он также оставляет запятую в остатке, что является вторым вопросом. Либо это разделитель, либо нет.

# testcases : string , #of words to remove, desired answer 
s=['manipulate widgets add,1,2,3', 
    'manipulate,widgets,add,1,2,3', 
    'manipulate ,widgets  add , 1, 2 , 3', 
    'manipulate ,widgets  add , 1, 2 , 3', 
    'LET X = 42', 
    'LET FOUR = 2 + 2', 
    'LET FOUR = 2 + 2', 
    'A -1 B text.txt''] 

X= [3,2,2,3,3,2,3,2] 

a= [',1,2,3', 
    'add,1,2, 3', 
    'add , 1, 2 , 3', 
    ', 1, 2 , 3', 
    '42', 
    '= 2 +2', 
    '2 +2', 
    'B text.txt'] 

#Just to make it interesting, the input string can contain multiple spaces or tabs between words; 
#only one comma, but that might also have spaces pre/suc-ceeding it  
# <-- does that make the comma a word? 

# only delimiters are space and tab, not commas  
# <-- **does that make a single standing comma a word? ** 
# **2nd test case is contradictory to later statements, as comma is a delimiter here!** 
+0

Мои извинения. Запятая не является разделителем. Я обновлю вопрос. – Mawg

1

Это похоже на работу для ваших тестов:

>>> def remover(line, words): 
... parsed = re.split('(\s*,{0,1}\s*)', line, maxsplit=words) 
... return ''.join(parsed[-2:]).lstrip() 
... 
>>> remover('LET FOUR = 2 + 2', 2) 
'= 2 + 2' 
>>> remover('A -1 B text.txt', 2) 
'B text.txt' 
>>> remover('manipulate widgets add,1,2,3', 3) 
',1,2,3' 
>>> remover('manipulate,widgets,add,1,2,3', 2) 
',add,1,2,3' 
>>> remover('manipulate ,widgets  add , 1, 2 , 3', 2) 
'add , 1, 2 , 3' 

Это не было ясно, что если что-то делать с ведущими пропуски. Если он должен быть сохранен, можно удалить lstrip().

1

Я думаю, что этот метод очень прост и не использует регулярное выражения:

def delete_leading_words(string, num_words, delimeters=' \t,'): 
    if num_words == 0: 
     return string 

    i = 0 
    while i < len(string) and string[i] in delimeters: 
     i += 1 
    while i < len(string) and string[i] not in delimeters: 
     i += 1 

    return delete_leading_words(string[i:], num_words-1, delimeters) 
+0

Elegane. Бонусные очки за хороший кусок рекурсия – Mawg

+0

Спасибо Mawg. Однако я понимаю, что можно было попытаться удалить слишком много слов и получить ошибку за пределами границ. См. Отредактированный код для исправления (проверка границ во время цикла). – BallpointBen

Смежные вопросы