2016-08-25 8 views
2

Я хотел бы порезать список строк на основе подстрок возможно содержащиеся в его элементах:список Нарезка с условиями склейки разные строки

l = ['Some long text', 'often begins', ' with ', 
    'impenetrable fog ', 'which ends', ' somewhere further'] 
startIndex = [u for u, v in enumerate(l) if 'begins' in v)][0] 
finalIndex = [u for u, v in enumerate(l) if 'ends' in v)][0] 

, так что я получаю:

' '.join(l[startIndex:finalIndex]) == 'often begins with impenetrable fog' 

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

Первые и последние элементы, возможно, должны быть удалены из, но я предполагаю, что это вопрос регулировочных индексов на 1. Моего кодом работает в идеальных случаях, но часто не в состоянии, как структура и содержание l не очень предсказуемы. Отсутствие одного или обоих элементов, соответствующих условиям, должно заканчиваться окончательной строкой None.

Учитываются ли релевантные значения или отображение лямбда-функции для применения обоих условий?

+0

Можете ли вы предоставить наглядный пример? Вы хотите, чтобы все «строки» в «списке» находились между строкой 'start' и' end'.Например: '['How May', 'I help', 'You with', 'Your Problem', 'Andreas']'. С start = 'help' и end =' Problem'. Каким должен быть ваш необходимый результат? –

+0

Да, я хотел бы получить «Вы с вашей проблемой» в качестве вывода с вашим примером. Спасибо, что ответили! –

+0

Кстати, что вы уже пробовали с помощью карт и лямбда-функций? –

ответ

1

Try:

l = ['Some long text', 'often begins', 'with', 'impenetrable fog', 'which ends', 'somewhere further'] 

""" 
return the index of the phase in 'phases' if phase contains 'word' 
if not found, return 'default' 
""" 
def index(phases, word, default): 
    for i, s in enumerate(phases): 
     if word in s: return i 
    return default 

startIndex = index(l, "long", -1) 
finalIndex = index(l, "somewhere", len(l)) 

print(' '.join(l[startIndex+1:finalIndex])) 
1

Или с next():

l = ['Some long text', 'often begins', ' with ', 'impenetrable fog ', 
    'which ends', ' somewhere further'] 

startIndex = next((u for u, v in enumerate(l) if 'begins' in v), 0) 
finalIndex = next((u for u, v in enumerate(l) if 'ends' in v), 0) 

if (startIndex and finalIndex) and (finalIndex > startIndex): 
    sentence = ' '.join(l[startIndex:finalIndex]) 
else: 
    sentence = None 
print(sentence) 

Похожие в списке понимание, execpt не возвращает список, но первый элемент он найден. если он не нашел ничего, он возвращает дополнительный элемент (здесь '0')

Таким образом, если нет 'begins' или в списке нет 'ends', вы не должны печатать ничего. Таким образом, это позволяет проверить, если 'ends' подходит к 'begins'.

Я также люблю просмотр списка, но иногда то, что вам нужно, это не список.

РЕШЕНИЕ ДЛЯ ПРЕДВАРИТЕЛЬНОГО ПОЛЬЗОВАТЕЛЯ:

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

l = ['Some long text ends here', 'often begins', ' with ', 'which ends'] 
        ^^^ 

Чтобы избежать этого, вы можете использовать генератор с send(), чтобы повторять только один раз в вашем списке.

def get_index(trigger_word): 
    for u, v in enumerate(l): 
     if trigger_word in v: 
      trigger_word = yield u 

gen = get_index('begins') 
startIndex = gen.send(None) 
finalIndex = gen.send('ends') 

Здесь yield позволяет получить индекс, не выходя из функции.

Это лучше, но если в списке begins или ends, будет исключение StopIteration. Чтобы этого избежать, вы можете просто сделать бесконечный цикл на yield 0. Теперь полное решение будет:

def get_index(l, trigger_word): 
    for u, v in enumerate(l): 
     if trigger_word in v: 
      trigger_word = yield u 
    while True: 
     yield 0 

def concat_with_trigger_words(l):   
    gen = get_index(l, 'begins') 
    startIndex = gen.send(None) 
    finalIndex = gen.send('ends') 
    return ' '.join(l[startIndex:finalIndex]) if (startIndex and finalIndex) else None 

# Here some list for free lists for your future unitary tests ;) 

l_orignal = ['Some long text here', 'often begins', ' with ', 
      'impenetrable fog ', 'which ends', ' somewhere further'] 
l_start_with_ends = ['ends', 'often begins', ' with ', 
        'impenetrable fog ', 'which ends', 'begins'] 
l_none = ['random', 'word'] 
l_without_begin = ['fog', 'ends here'] 
l_without_end = ['begins', 'but never' '...'] 

print(concat_with_trigger_words(l_orignal)) # often begins with impenetrable fog 
print(concat_with_trigger_words(l_start_with_ends)) # often begins with impenetrable fog 
print(concat_with_trigger_words(l_none)) # None 
print(concat_with_trigger_words(l_without_end)) # None 
print(concat_with_trigger_words(l_without_begin)) # None 
1
>>> l = ['Some long text', 'often begins', ' with ', 
...  'impenetrable fog ', 'which ends', ' somewhere further'] 
>>> start, end = 'begins', 'ends' 
>>> key_index = {'start': {'word': start, 'index': -1}, 
       'end': {'word': end, 'index': -1}} 
>>> for i, val in enumerate(l): 
...  if key_index['start']['word'] in val: 
...   key_index['start']['index'] = i 
...  elif key_index['end']['word'] in val: 
...   key_index['end']['index'] = i 
... 
>>> start_index, end_index = key_index['start']['index'], key_index['end']['index'] 
>>> my_list = l[start_index+1:end_index] if start_index >=0 and end_index >= 0 and start_index+1 < end_index else None 
>>> my_list 
[' with ', 'impenetrable fog '] 
Смежные вопросы