Home > Net >  determining which integers are out of sequence in a python list
determining which integers are out of sequence in a python list

Time:12-24

I have a list of indexes:

[24, 175, 78, 80, 659, 126, 141, 149, 29, 158, 178, 179]

I want to know how to identify (and remove) which ones are out of sequence.

desired outcome:

[24, 78, 80, 126, 141, 149, 158, 178, 179]

As a human, I see that 175, 659, and 29 stand out, but am unsure of how to do this programmatically. I have tried a pairwise comparison (a subset of the index returning the first value if sub_arr[0] < sub_arr[1].

new_ls = []

def eval_adjacent(ls):
    if ls[1] > ls[0]:
        return ls[0]

for n, ele in enumerate(idx_ls[:-1]):
    res = eval_adjacent(idx_ls[n:n 2])
    if res:
        new_ls.append(res)

However, if the integer is less than it should be, this won't work (29). Have thought about iterating in both directions but am starting to think this is not the way to go.

I think comparing it to sorted(ls) is potentially easier - but am not sure how to select the ones which are desirable (rejecting the remainder).

Can anyone point me in the right direction?

CodePudding user response:

It seems like you want the longest increasing subsequence.

Try this:

from math import floor


# from https://en.wikipedia.org/wiki/Longest_increasing_subsequence
def lis(X):
    N = len(X)
    P = [0] * N
    M = [0] * N
    M[0] = -1

    L = 0
    for i in range(N):
        lo = 1
        hi = L   1
        while lo < hi:
            mid = lo   floor((hi-lo)/2)
            if X[M[mid]] > X[i]:
                hi = mid
            else:
                lo = mid   1

        newL = lo

        P[i] = M[newL-1]
        M[newL] = i

        if newL > L:
            L = newL

    S = [0] * N
    k = M[L]
    for j in range(L-1, -1, -1):
        S[j] = X[k]
        k = P[k]

    S = [el for el in S if el != 0]
    return S


data = [24, 175, 78, 80, 659, 126, 141, 149, 29, 158, 178, 179]
print(lis(data))  # => [24, 78, 80, 126, 141, 149, 158, 178, 179]

CodePudding user response:

You can use dynamic programming:

def long_inc_seq(lst):
    dp = [[n] for n in lst]
    for i in range(len(lst)):
        for j in range(i):
            if lst[i] > lst[j] and len(dp[i]) < len(dp[j])   1:
                dp[i] = dp[j]   [lst[i]]
    return max(dp, key=len)

result = long_inc_seq([24, 175, 78, 80, 659, 126, 141, 149, 29, 158, 178, 179])
print(result)

Output:

[24, 78, 80, 126, 141, 149, 158, 178, 179]

For explanation:

# The inside of dp for the above example:
>>> dp
[[24],
 [24, 175],
 [24, 78],
 [24, 78, 80],
 [24, 78, 80, 659],
 [24, 78, 80, 126],
 [24, 78, 80, 126, 141],
 [24, 78, 80, 126, 141, 149],
 [24, 29],
 [24, 78, 80, 126, 141, 149, 158],
 [24, 78, 80, 126, 141, 149, 158, 178],
 [24, 78, 80, 126, 141, 149, 158, 178, 179]]

CodePudding user response:

You can use list comprehension and windowed from more_itertools:

  • the windowed function allows you to create a sliding window of the set
  • each sliding window is examined for numbers that are out of sequence
  • these numbers are listed in the variable called nums_to_reject
  • and are then deleted from the original list of indices to produce the result

Code:

from more_itertools import windowed

indices = [24, 175, 78, 80, 659, 126, 141, 149, 29, 158, 178, 179]

nums_to_reject = [item[1] for item in windowed(indices, 3) if item[0] < item[2] < item[1] or item[1] < item[2] > item[0] > item[1]]    
result = sorted(list(set(indices) - set(nums_to_reject)))        

print(result)

Output:

[24, 78, 80, 126, 141, 149, 158, 178, 179]

CodePudding user response:

Here's a method that I think can be understood by any type of python programmer: (I'm assuming that there are no 2 subsequent numbers out of sequence)

my_list = [24, 175, 78, 80, 659, 126, 141, 149, 29, 158, 178, 179]
my_list2 = []
for i in range(len(my_list)):
    try:
        if not (my_list[i   1] > my_list[i] and my_list[i   1] > my_list[i   2]):
            my_list2.append(my_list[i   1])
    except(IndexError):  # we add this to prevent INDEX OUT OF RANGE exception
        pass
print(my_list2)

OUTPUT

[78, 80, 126, 141, 29, 158, 178]
  • Related