List contains only integers. I need to select elements with the next requirements (every requirement is a separate problem):
Elements between 1 and 1:
[2,1,3,1,3] -> [3]
,[2,1,3,4,1,3] -> [3,4]
Elements between same numbers:
[1,2,3,2] -> [3], [1,4,3,5,4] -> [3,5]
Elements that have more than one same neighborhood:
[1,1,3] -> [1,1], (2 consecutive 1s), [1,1,3,2,2,2,1] -> [1,1,2,2,2] (2 consecutive 1s and 3 consecutive 2s)
What is general approach to this problem? I have worked with filter but only with one parameter predicate: filter(lambda x: (x%2 == 0), numbers)
Is there another approach rather than nested for loops? Maybe more functional style. Is it possible to use convolutions as a solution?
CodePudding user response:
For Q1, you can create a list with the indices of 1s and iterate over the list again to find the items between ones.
ones = [i for i,x in enumerate(lst) if x==1]
for i,j in zip(ones, ones[1:]):
print(lst[i 1:j])
Output:
[2,1,3,1,3] -> [3]
[2,1,3,4,1,3] -> [3, 4]
For Q2, similar to Q1, iterate over the list to find the indices of items and keep them in a dictionary. Then iterate over it to find the numbers that occur more than once and print out the items between these numbers:
d = {}
for i,x in enumerate(lst):
d.setdefault(x, []).append(i)
for k,indices in d.items():
if len(indices)>1:
for i,j in zip(indices, indices[1:]):
print(lst[i 1:j])
Output:
[1,2,3,2] -> [3]
[1,4,3,5,4] -> [3, 5]
CodePudding user response:
Here is a solution for Q1/Q3 using itertools
:
Q1
This one groups by equality to 1, this then drops the first and last group (either 1 or not 1 but in any case we don't want to keep), then drops the groups equal to 1 leaving only the inner groups is any.
l1 = [2,1,3,4,1,3,6,1,0]
from itertools import groupby, chain
list(chain.from_iterable(g for k,g in
[(k,list(g)) for k,g in
groupby(l1, lambda x: x==1)][1:-1]
if not k))
# [3, 4, 3, 6]
Q3
Here we group by identical consecutive values and filter using the group length if greater than 1.
l3 = [1,1,3,2,2,2,1]
from itertools import groupby, chain
list(chain.from_iterable(l for k,g in groupby(l3) if len(l:=list(g))>1))
# [1, 1, 2, 2, 2]
CodePudding user response:
Part 3 can be solved without nested for loops using itertools.groupby
from itertools import groupby
def repeating_sections(lst):
out_lst = []
for key, group in groupby(lst):
_lst = list(group)
if len(_lst) > 1:
out_lst = _lst
return out_lst
print(repeating_sections([1, 1, 3, 2, 2, 2, 1])
# [1, 1, 2, 2, 2]
CodePudding user response:
Maybe you can create a function? It meets all three criteria
def filterNumbers(numList, targetNum) -> list:
firstPosition = numList.index(targetNum)
lastPosition = numList.index(targetNum, firstPosition 2)
while True:
try:
if lastPosition != (len(numList)-1):
if numList[lastPosition] == numList[lastPosition 1]:
lastPosition = lastPosition 1
continue
break
except Exception as e:
print(e)
resultList = numList[firstPosition 1:lastPosition]
return resultList
Condition 1:
test1 = [2, 1, 3, 1, 3]
filterNumbers(test1, 1)
#Output:
[3]
Condition 2:
test2 = [1, 4, 3, 5, 4]
filterNumbers(test2, 4)
#Output:
[3, 5]
Condition 3:
test3 = [1,1,3,2,2,2,1]
filterNumbers(test3, 1)
#Output
[1, 3, 2, 2, 2]
I am assuming there is a typo while you were writing the third condition because you skipped the 3 and included the first 1.