okeoke
okeoke

Reputation: 93

Join consecutive pairs of strings in a list if they meet a condition

Given two lists:

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

with the assumption len(list2) == 2,

I was wondering how to get an output like this:

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

Essentially any instance of list2 within list1 (in that order), should concatenate in the original list1 and output (after checking all possibilities).

What I tried so far:

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)

But keep getting an error:

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

Upvotes: 3

Views: 715

Answers (7)

Leporello
Leporello

Reputation: 658

Version with arbitrary list2 length:

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']

EDIT: code fixed per comments, adding the if el == list2[0] branch.

Upvotes: 0

Deepstop
Deepstop

Reputation: 3807

Assuming the question is why you are getting an error, this line

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

modifies list1, and actually makes it shorter. So when you are looping on a range that is the length of list 1, making the list shorter means that the loop counter i will eventually be out of range, because the elements of the list you intended to find with the index are gone.

You also need to remember that lists are indexed from 0 to n - 1, where n is the length of the list, so this statement

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

looks like it really should be

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

Also the outer loop is based on range(0, l - 1) means that it will loop through every index except the last one. So unless you really want to avoid looking at the last element of the list, which I don't think you do based on your requirements, you would use range(l), which produces indexes from 0 to l - 1.

Upvotes: 1

iGian
iGian

Reputation: 11183

I'd like to suggest this method which returns a generator:

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])

In this case:

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

It returns:

res = join_if_ref(list1, list2)
print(list(res))
#=> ['a', 'bcd', 'e', 'f', 'b', 'c', 'b', 'd', 'f', 'c', 'bcd', 'k', 's']

Upvotes: 0

lenik
lenik

Reputation: 23498

Try this, should work for any length of 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) )

checking the result :

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

Upvotes: 2

sahasrara62
sahasrara62

Reputation: 11228

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)

output

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

Upvotes: 0

bharatk
bharatk

Reputation: 4315

Try this:

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']

Upvotes: 0

Rakesh
Rakesh

Reputation: 82765

This is one approach using list slicing.

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)

Output:

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

Upvotes: 0

Related Questions