Соедините последовательные пары строк в списке, если они удовлетворяют условию - PullRequest
2 голосов
/ 20 июня 2019

Учитывая два списка:

list1 = ["a","b","c","d","e","f","b","c","b","d","f","c","b","e"]
list2 = ["b","c"]

с предположением len(list2) == 2,

Мне было интересно, как получить вывод, подобный этому:

['a', 'bc', 'd', 'e', 'f', 'bc', 'b', 'd', 'f', 'c', 'b', 'e']

По существулюбой экземпляр list2 в списке list1 (в таком порядке) должен объединяться в исходный список list1 и выводиться (после проверки всех возможностей).

То, что я пробовал до сих пор:

l = len(list1)

for i in range(0,l-1):
    if list1[i] == list2[0]:
        if list1[i+1] == list2[1]:
            a = i
            b = i+1
            list1[a:b+1] = [''.join(list1[a:b+1])]
            l = l - 1
            print(list1)

Но сохранитьполучаю ошибку:

if list1[i] == list2[0]: IndexError: list index out of range

Ответы [ 7 ]

2 голосов
/ 20 июня 2019

Попробуйте, это должно работать для любой длины list2:

split_pattern = ''.join(list2)
chunks = ''.join(list1).split(split_pattern)

result = list(chunks[0])
for c in chunks[1:] :
    result.append( split_pattern )
    result.extend( list(c) )

проверка result:

>>> result
['a', 'bc', 'd', 'e', 'f', 'bc', 'b', 'd', 'f', 'c', 'b', 'e']
1 голос
/ 20 июня 2019

Если вопрос в том, почему вы получаете ошибку, эта строка

                list1[a:b+1] = [''.join(list1[a:b+1])]

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

Вам также нужно помнить, что списки индексируются от 0 до n - 1, где n - длина списка, поэтому это утверждение

if list1[i+1] == list2[1]:

выглядит так, как должно быть

if list[i] == list2[0]:

Кроме того, внешний цикл основан на range(0, l - 1), что означает, что он будет проходить по всем индексам, кроме последнего. Поэтому, если вы действительно не хотите избегать просмотра последнего элемента списка, что, я думаю, вы не делаете в зависимости от ваших требований, вы должны использовать range(l), который производит индексы из 0 to l - 1.

0 голосов
/ 20 июня 2019

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

def join_if_ref(main_list, ref_list):
  n, s = len(ref_list), "".join(ref_list)
  i, size = 0, len(main_list)
  while i < size-n+1:
    j = "".join(main_list[i:i+n])
    if j == s:
      yield j
      i += n - 1
    else:
      yield main_list[i]
    if i < size: i += 1
  for k in range(size-i):
    yield(main_list[k+i])

В этом случае:

list1 = ["a","b","c","d","e","f","b","c","b","d","f","c","b","c","d","k","s"]
list2 = ["b","c","d"]

Возвращает:

res = join_if_ref(list1, list2)
print(list(res))
#=> ['a', 'bcd', 'e', 'f', 'b', 'c', 'b', 'd', 'f', 'c', 'bcd', 'k', 's']
0 голосов
/ 20 июня 2019
def new_f(l1,l2):
    for i,j in zip(l2,l1):
        if i!=j:
            return False
    return True


def func(l1,l2):

    res=[]    
    index = 0    
    l2_string = ''.join(l2)

    while index<len(l1):        
        if l1[index]==l2[0] and new_f(l1[index:index+len(l2)], l2):          # if first element found then checck compare with list2
            # compare with list2 if elemnt match with first elment of list2
            res.append(l2_string)
            index+=len(l2)
        else:
            res.append(l1[index])               
        index+=1
    return res

list1 = ["a", "b","b", "c", "d", "e", "f", "b", "c", "b", "d", "f", "c", "b", "e"]
list2 = ["b", "c"]

result= func(list1,list2)
print(result)

выход

    ['a', 'b', 'bc', 'e', 'f', 'bc', 'd', 'f', 'c', 'b', 'e']
0 голосов
/ 20 июня 2019

Версия с произвольной длиной list2:

def sublist_concatenate(list1, list2):
    N = len(list2)
    fullset = ''.join(list2)
    outlist = []
    i = 0  # counts the number of matches so far

    for el in list1:
        if el == list2[i]:  # hold matching elements so far
            i += 1
            if i == N:  # we have matched N times, so we have the whole set
                outlist.append(fullset)
                i = 0
        else:  # not a match for the next position
            outlist += list2[0:i] # add all previously-passed elements
            # check whether it is a match for the first position though
            if el == list2[0]:
                i = 1
            else:
                outlist.append(el)
                i = 0

    return outlist


l1 = ["a", "b", "b", "c", "d", "e", "f",
      "b", "c", "b", "d", "f", "c", "b", "e"]
l2 = ["b", "c"]

print sublist_concatenate(l1, l2)
# ['a', 'b', 'bc', 'd', 'e', 'f', 'bc', 'b', 'd', 'f', 'c', 'b', 'e']

РЕДАКТИРОВАТЬ: код исправлен для комментариев, добавив ветку if el == list2[0].

0 голосов
/ 20 июня 2019

Попробуйте это:

list1 = ["a","b","c","d","e","f","b","c","b","d","f","c","b","e"]
list2 = ["b","c"]
l = len(list1)
new_list = []
last_merge = False

for i in range(0,l):
    # match list1 index i element with list2 first element
    if list1[i] == list2[0]:
        # match list1 index i+1 element with list2 second element
        if i+1 <= l and list1[i+1] == list2[1]:
            # merge and append list1 index i and i+1 element
            new_list.append(list1[i]+list1[i+1])
            # mark merge as true
            last_merge = True
        else:
            # append list1 index i element
            new_list.append(list1[i])
    else:
        # check list index i element is merge with last element then mark last_merge as False and continue iterate list
        if last_merge is True:
            last_merge = False
            continue

        # append list1 index i element
        new_list.append(list1[i])

print(new_list)

O / P:

['a', 'bc', 'd', 'e', 'f', 'bc', 'b', 'd', 'f', 'c', 'b', 'e']
0 голосов
/ 20 июня 2019

Это один подход, использующий нарезку списка.

Ex:

list1 = ["a","b","c","d","e","f","b","c","b","d","f","c","b","e"]
list2 = ["b","c"]

l = len(list2)
result = []
skip = 0
for i, v in enumerate(list1):
    if skip:
        skip -= 1
        continue
    if list1[i:l+i] == list2:           #Check for sub-element
        result.append("".join(list2))
        skip = l-1                      #Skip flag
    else:
        result.append(v)
print(result)

Выход:

['a', 'bc', 'd', 'e', 'f', 'bc', 'b', 'd', 'f', 'c', 'b', 'e']
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...