Subline Based Listing

I have the following list:

['1(Reg)', '100', '103', '102', '100', '2(Reg)', '98', '101', '100', '3(Reg)', '96', '99', '98', '4(Reg)', '100', '100', '100', '100', '5(Reg)', '98', '99', '99', '100', '6(Reg)', '99.47', '99.86', '99.67', '100']

I want to split this list into several lists so that each count gets the substring "(Reg)":

[['1(Reg)', '100', '103', '102', '100'],
['2(Reg)', '98', '101', '100'],
['3(Reg)', '96', '99', '98'],
['4(Reg)', '100', '100', '100', '100'],
['5(Reg)', '98', '99', '99', '100'],
['6(Reg)', '99.47', '99.86', '99.67', '100']]

I tried joining a delimited list and splitting it into (Reg), but that didn't work. How can I split a list into a nested list as above?

+4
source share
8 answers

A slightly different (optimized) version of the WVO answer:

splitted = []

for item in l:
    if '(Reg)' in item:
        splitted.append([])
    splitted[-1].append(item)

#[['1(Reg)', '100', '103', '102', '100'], ['2(Reg)', '98', '101', '100'], 
# ['3(Reg)', '96', '99', '98'], ['4(Reg)', '100', '100', '100', '100'], 
# ['5(Reg)', '98', '99', '99', '100'], 
# ['6(Reg)', '99.47', '99.86', '99.67', '100']]
+5
source

You can use itertools.groupbywith regular expressions:

import itertools
import re
s = ['1(Reg)', '100', '103', '102', '100', '2(Reg)', '98', '101', '100', '3(Reg)', '96', '99', '98', '4(Reg)', '100', '100', '100', '100', '5(Reg)', '98', '99', '99', '100', '6(Reg)', '99.47', '99.86', '99.67', '100']
new_data = [list(b) for _, b in itertools.groupby(s, key=lambda x:bool(re.findall('\d+\(', x)))]
final_data = [new_data[i]+new_data[i+1] for i in range(0, len(new_data), 2)]

Conclusion:

[['1(Reg)', '100', '103', '102', '100'], 
 ['2(Reg)', '98', '101', '100'], 
 ['3(Reg)', '96', '99', '98'], 
 ['4(Reg)', '100', '100', '100', '100'], 
 ['5(Reg)', '98', '99', '99', '100'], 
 ['6(Reg)', '99.47', '99.86', '99.67', '100']]
+5
source

, :

from itertools import zip_longest

lst = ['1(Reg)', '100', '103', '102', '100', '2(Reg)', '98', '101', '100',
       '3(Reg)', '96', '99', '98', '4(Reg)', '100', '100', '100', '100',
       '5(Reg)', '98', '99', '99', '100', '6(Reg)', '99.47', '99.86', '99.67', '100']

indices = [i for i, j in enumerate(lst) if '(Reg)' in j]
lst_new = [lst[i:j] for i, j in zip_longest(indices, indices[1:])]

# [['1(Reg)', '100', '103', '102', '100'],
#  ['2(Reg)', '98', '101', '100'],
#  ['3(Reg)', '96', '99', '98'],
#  ['4(Reg)', '100', '100', '100', '100'],
#  ['5(Reg)', '98', '99', '99', '100'],
#  ['6(Reg)', '99.47', '99.86', '99.67', '100']]
+5

, - ( @jp_data_analysis ):

>>> from pprint import pprint
>>> d = ['1(Reg)', '100', '103', '102', '100', '2(Reg)', '98', '101', '100', '3(Reg)', '96', '99', '98', '4(Reg)', '100', '100', '100', '100', '5(Reg)', '98', '99', '99', '100', '6(Reg)', '99.47', '99.86', '99.67', '100']
>>> idx = filter(lambda i: d[i].endswith("(Reg)"), range(len(d))) + [len(d)]
>>> idx
[0, 5, 9, 13, 18, 23, 28]
>>> res = [d[idx[i-1]:idx[i]] for i in range(1,len(idx))]
>>> pprint(res)
[['1(Reg)', '100', '103', '102', '100'],
 ['2(Reg)', '98', '101', '100'],
 ['3(Reg)', '96', '99', '98'],
 ['4(Reg)', '100', '100', '100', '100'],
 ['5(Reg)', '98', '99', '99', '100'],
 ['6(Reg)', '99.47', '99.86', '99.67', '100']]

: idx , (Reg) ( ). res .

: , , : ? - ? , ? , ? -, Twitter:)

+4

for : , , , . :

rows = []
row = []
for word in data:
    if '(Reg)' in word:
        rows.append(row)
        row = []
    row.append(word)
rows.append(row)

data .

However, there is a problem with this: first it will add an empty string (if it has the first element in it (Reg). We can prevent this by adding non-empty rows, for example:

rows = []
row = []
for word in data:
    if '(Reg)' in word:
        if row:
            rows.append(row)
        row = []
    row.append(word)
if row:
    rows.append(row)

We can generalize the above to a special function:

split_at(data, predicate, with_empty=False):
    rows = []
    row = []
    for word in data:
        if predicate(word):
            if with_empty or row:
                rows.append(row)
            row = []
        row.append(word)
    if with_empty or row:
        rows.append(row)
    return rows

Then we can call it the following:

split_at(our_list, lambda x: '(Reg)' in x)
+2
source

Using itertools.groupby

lst = ['1(Reg)', '100', '103', '102', '100', '2(Reg)', '98', '101', '100', '3(Reg)', '96', '99', '98', '4(Reg)', '100', '100', '100', '100', '5(Reg)', '98', '99', '99', '100', '6(Reg)', '99.47', '99.86', '99.67', '100']
from itertools import groupby
[a+b for a,b in zip(*([iter(list(g) for k, g in groupby(lst, lambda x:'Reg' in x))]*2))]

Conclusion:

[['1(Reg)', '100', '103', '102', '100'],
 ['2(Reg)', '98', '101', '100'],
 ['3(Reg)', '96', '99', '98'],
 ['4(Reg)', '100', '100', '100', '100'],
 ['5(Reg)', '98', '99', '99', '100'],
 ['6(Reg)', '99.47', '99.86', '99.67', '100']]
+2
source

Here is another way without libraries. This is a list comprehension based on DYZ answer:

w = []
[w.append([]) or w[-1].append(e) if '(Reg)' in e else w[-1].append(e) for e in data]
+2
source

You can also try the following:

from itertools import groupby

lst = ['1(Reg)', '100', '103', '102', '100', '2(Reg)', '98', '101', '100',
       '3(Reg)', '96', '99', '98', '4(Reg)', '100', '100', '100', '100',
       '5(Reg)', '98', '99', '99', '100', '6(Reg)', '99.47', '99.86', '99.67', '100']

grouped = [list(g) for k, g in groupby(lst, key = lambda x: x.endswith('(Reg)'))]

result = [x + y for x, y in zip(grouped[0::2], grouped[1::2])]

print(result)

What outputs:

[['1(Reg)', '100', '103', '102', '100'], ['2(Reg)', '98', '101', '100'], ['3(Reg)', '96', '99', '98'], ['4(Reg)', '100', '100', '100', '100'], ['5(Reg)', '98', '99', '99', '100'], ['6(Reg)', '99.47', '99.86', '99.67', '100']]
+1
source

Source: https://habr.com/ru/post/1693126/


All Articles