Reputation: 8119
I have a list 'r' like this:
[["", 1], ["this is a text line", 2], ["this is a text line", 3], ["this is a text line", 4], ["", 5], ["", 6], ["this is a text line", 7],["this is a text line", 8], ["this is a text line", 9], ["this is a text line", 10], ["", 11], ["this is a text line", 12], ["this is a text line", 13], ["this is a text line", 14], ["", 15], ["this is a text line", 16], ["this is a text line", 17], ["this is a text line", 18], ["", 19]]
To know where are my empty lines and lines with text I filter my list:
empty = [x[1] for x in r if regex.search("^\s*$", x[0])]
text = [x[1] for x in r if regex.search("\S", x[0])]
output:
empty = [1, 5, 6, 11, 15, 19]
text= [2, 3, 4, 7, 8, 9, 10, 12, 13, 14, 16, 17, 18]
What I want to do is to combine the numbers in text if they are in sequence (text[i]-text[i+1]) = +1 (in order to define the paragraphs):
finaltext = [[2, 3, 4], [7, 8, 9, 10], [12, 13, 14], [16, 17, 18]]
finaltext including empty = [[2, 3, 4, 5, 6], [7, 8, 9, 10, 11], [12, 13, 14, 15], [16, 17, 18, 19]]
How can I group elements in a list based on a condition?
Upvotes: 3
Views: 130
Reputation: 3547
Using itertools.groupby
from itertools import groupby, zip_longest
grp_list = [list(g) for k,g in groupby(r, lambda x:x[0]=='')]
grp_list = grp_list[1:] if r[0][0] == '' else grp_list
text = [[j[1] for j in i] for i in grp_list]
finaltext = text[::2]
print (finaltext)
#[[2, 3, 4], [7, 8, 9, 10], [12, 13, 14], [16, 17, 18]]
finaltext_including_empty = [i+j for i,j in zip_longest(text[::2], text[1::2], fillvalue=[])]
print (finaltext_including_empty)
#[[2, 3, 4, 5, 6], [7, 8, 9, 10, 11], [12, 13, 14, 15], [16, 17, 18, 19]]
groupby
groups the list into chunks of sublists based on condition which here is lambda x:x[0]==''
, meaning create a list chunk till the point where you see an empty string, and follow this rule till the end like below
[[['', 1]], [['this is a text line', 2], ['this is a text line', 3], ['this is a text line', 4]], [['', 5], ['', 6]],........]
Upvotes: 3
Reputation: 20434
Pure Python solution without any modules
:
This can be done using modules
such as with numpy
and groupby
, but I thought it would be call to attempt without them, just with plain Python
. Here is my solution:
text = [2, 3, 4, 7, 8, 9, 10, 12, 13, 14, 16, 17, 18]
s = 0
finaltext = []
for i in range(len(text)-1):
if text[i] + 1 != text[i+1]:
finaltext.append(text[s:i+1])
s = i+1
finaltext.append(text[s:])
which gives finaltext
as:
[[2, 3, 4], [7, 8, 9, 10], [12, 13, 14], [16, 17, 18]]
Update
To get both of the lists
(not sure why you would want to), you can use the following:
empty = [1, 5, 6, 11, 15, 19]
text = [2, 3, 4, 7, 8, 9, 10, 12, 13, 14, 16, 17, 18]
s = 0
finaltext = []
finaltext_including_empty = []
for i in range(len(text)-1):
if text[i] + 1 != text[i+1]:
finaltext.append(text[s:i+1])
finaltext_including_empty.append(list(range(text[s], text[i+1])))
s = i+1
finaltext.append(text[s:])
finaltext_including_empty.append(list(range(text[s],max(empty[-1]+1, text[-1]+1))))
which gives finaltext
the same as before and finaltext_including_empty
as:
[[2, 3, 4, 5, 6], [7, 8, 9, 10, 11], [12, 13, 14, 15], [16, 17, 18, 19]]
Upvotes: 1
Reputation: 764
pip install more_itertools
from more_itertools import chunked
empty = [1, 5, 6, 11, 15, 19]
text= [2, 3, 4, 7, 8, 9, 10, 12, 13, 14, 16, 17, 18]
finaltext_ = sorted(empty + text)
list(chunked(finaltext_,4))
[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16], [17, 18, 19]]
Upvotes: 1