Split list into sublists of elements between opening and closing tokens

Viewed 381

I have a list of strings (see below). I want to get the elements in the list by looking for two specific tokens (begin and end) and then save all the strings present between those tokens.

For example, I have below list and I want to get all strings between any occurrence of the strings 'RATED' and 'Like'. There can be multiple occurrences of these subsequences, too.

['RATED',
 '  Awesome food at a good price .',
 'Delivery was very quick even on New Year\xe2\x80\x99s Eve .',
 'Please try crispy corn and veg noodles From this place .',
 'Taste maintained .',
 'Like',
 '1',
 'Comment',
 '0',
 'Share',
 'Divyansh Agarwal',
 '1 Review',
 'Follow',
 '3 days ago',
 'RATED',
 '  I have tried schezwan noodles and the momos with kitkat shake',
 "And I would say just one word it's best for the best reasonable rates.... Gotta recommend it to everyone",
 'Like']

I have tried different methods, like regex, but none solved the problem.

7 Answers

You could use regular expression First you need to join your list with some delimiter that will not occur in text

delimiter = "#$#"
bigString = delimiter + delimiter.join(yourList) + delimiter

After that you could use regular expression

results = re.findall(r'#\$#RATED#\$#(.*?)#\$#Like#\$#', bigString)

Now you just have to iterate all results and split string with delimiter

for s in results:
    print(s.split(delimiter))

I'd suggest you learn about index lookup and slicing on sequence types:

Example:

def group_between(lst, start_token, end_token):
    while lst:
        try:
            # find opening token
            start_idx = lst.index(start_token) + 1
            # find closing token
            end_idx = lst.index(end_token, start_idx)
            # output sublist
            yield lst[start_idx:end_idx]
            # continue with the remaining items
            lst = lst[end_idx+1:]
        except ValueError:
            # begin or end not found, just skip the rest
            break

l = ['RATED','  Awesome food at a good price .', 'Delivery was very quick even on New Year’s Eve .', 'Please try crispy corn and veg noodles From this place .', 'Taste maintained .', 'Like', 
     '1', 'Comment', '0', 'Share', 'Divyansh Agarwal', '1 Review', 'Follow', '3 days ago',
     'RATED', '  I have tried schezwan noodles and the momos with kitkat shake', "And I would say just one word it's best for the best reasonable rates.... Gotta recommend it to everyone", 'Like'
]

for i in group_between(l, 'RATED', 'Like'):
    print(i)

The output is:

['  Awesome food at a good price .', 'Delivery was very quick even on New Year’s Eve .', 'Please try crispy corn and veg noodles From this place .', 'Taste maintained .']
['  I have tried schezwan noodles and the momos with kitkat shake', "And I would say just one word it's best for the best reasonable rates.... Gotta recommend it to everyone"]

You could try e.g.

rec = False
result = []
for s in lst:
    if s == 'Like':
        rec = False
    if rec:
        result.append(s)
    if s == 'RATED':
        rec = True

result

#[' Awesome food at a good price .',
# 'Delivery was very quick even on New Year’s Eve .',
# 'Please try crispy corn and veg noodles From this place .',
# 'Taste maintained .',
# ' I have tried schezwan noodles and the momos with kitkat shake',
# "And I would say just one word it's best for the best reasonable rates.... Gotta recommend it to everyone"]
def find_between(old_list, first_word, last_word):
    new_list = []
    flag = False
    for i in old_list:
        if i is last_word:
            break
        if i is first_word:
            flag = True
            continue
        if flag:
            new_list.append(i)
    return new_list

using regex you can do this is way .

a= ['RATED','  Awesome food at a good price .', 
 'Delivery was very quick even on New Year’s Eve .', 
 'Please try crispy corn and veg noodles From this place .', 
 'Taste maintained .', 'Like', '1', 'Comment', '0', 
 'Share', 'Divyansh Agarwal', '1 Review', 'Follow', 
 '3 days ago', 'RATED', 
 '  I have tried schezwan noodles and the momos with kitkat shake', "And I would say just one word it's best for the best reasonable rates.... Gotta recommend it to everyone", 
 'Like']


import re
string = ' '.join(a)
b = re.compile(r'(?<=RATED).*?(?=Like)').findall(string)
print(b)

output

['   Awesome food at a good price . Delivery was very quick even on New Year’s Eve . Please try crispy corn and veg noodles From this place . Taste maintained . ',
 "   I have tried schezwan noodles and the momos with kitkat shake And I would say just one word it's best for the best reasonable rates.... Gotta recommend it to everyone "]

An option without flags:

new_list = []
group = [] # don’t need if the list starts with 'RATED'

for i in your_list:
    if i == 'RATED':
        group = []
    elif i == 'Like':
        new_list.append(group[:])
    else:
        group.append(i)

You can use the below code which uses a simple for Loop:

l = ['RATED','  Awesome food at a good price .', 'Delivery was very quick even on New Year’s Eve .', 'Please try crispy corn and veg noodles From this place .', 'Taste maintained .', 'Like', 
     '1', 'Comment', '0', 'Share', 'Divyansh Agarwal', '1 Review', 'Follow', '3 days ago',
     'RATED', '  I have tried schezwan noodles and the momos with kitkat shake', "And I would say just one word it's best for the best reasonable rates.... Gotta recommend it to everyone", 'Like'
]

st, ed, aa = None, None, []
for k, v in enumerate(l):
    if v == "RATED":
        st = k
    if v == "Like":
        ed = k
    if st != None and ed!= None:
        aa.extend(l[st+1: ed])
        st = None
        ed = None

print (aa)

# ['  Awesome food at a good price .', 'Delivery was very quick even on New Year’s Eve .', 'Please try crispy corn and veg noodles From this place .', 'Taste maintained .', '  I have tried schezwan noodles and the momos with kitkat shake', "And I would say just one word it's best for the best reasonable rates.... Gotta recommend it to everyone"]
Related