Home > Back-end >  How to use Python to filter list based on the next requirements?
How to use Python to filter list based on the next requirements?

Time:12-31

List contains only integers. I need to select elements with the next requirements (every requirement is a separate problem):

  1. Elements between 1 and 1: [2,1,3,1,3] -> [3], [2,1,3,4,1,3] -> [3,4]

  2. Elements between same numbers: [1,2,3,2] -> [3], [1,4,3,5,4] -> [3,5]

  3. 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.

  • Related