Reputation: 93
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
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
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
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
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
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
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
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