1

Here is a test list :

test_list = [0,1,2,3,4,5,6,7,8,9]

How can I check if this list contains exactly thoses values 1,2,3 in this order (nothing in between values) ?

In this example, [0,1,2,3,4,5,6,7,8,9] contains '1,2,3' but doesn't contain '4,5,8' because there are items between 5 and 8, neither '3,2,1' because they are not in this order.

I guess this problem is easy to solve but I cannot find a nice and fast way to do it... Please, could you give me some clue? Kindly

chalbiophysics
  • 313
  • 4
  • 15

5 Answers5

3

You can use zip() to iterate 3 consecutive elements together and use any() to check whether any of the match is True. For example:

>>> my_list = [0,1,2,3,4,5,6,7,8,9]
>>> my_num = (1, 2, 3)

>>> any(x== my_num for x in zip(my_list, my_list[1:], my_list[2:]))
True

Refer below documents for more details:

Moinuddin Quadri
  • 46,825
  • 13
  • 96
  • 126
  • Nice. Is it possible to extend this to find any ‘pairs’ of consecutive numbers? – Daniel Hao Jan 21 '21 at 14:41
  • 1
    Yes, you can do like this `any(x==my_num for x in zip(*(my_list[i:] for i in range(len(my_num)))))`. But it is not worth it. If your tuple length is dynamic, Aven's answer is better – Moinuddin Quadri Jan 21 '21 at 14:53
2
def list_contains(A, B): 
    n = len(A) 
    return any(A == B[i:i + n] for i in range(len(B)-n + 1))
#Example
test_list = [0,1,2,3,4,5,6,7,8,9]
list_contains([1,2,3], test_list) # True
list_contains([4,5,8], test_list) # False
Aven Desta
  • 2,114
  • 12
  • 27
1

You can use zip to form subsets and check if your sequence is present in those.

Here is a generalized way to do it:

L = [0,1,2,3,4,5,6,7,8,9]
S = [1,2,3]

if tuple(S) in zip(*(L[i:] for i in range(len(S)))):
    print("found")
else:
    print("not found")

Using parameter unpacking *(... gives zip as many sub-lists as there are elements in S. Each of these sublist starts at a different offset so zip will receive L[0:],L[1:],L[2:],... which will form tuples with every sublist of length len(S).

If you don't want to use zip(), you can use indexes to form the subsets:

if S in (L[i:i+len(S)] for i in range(len(L))):
    print("found")
else:
    print("not found")

The string strategy requires that the separator avoids overstepping boundaries (e.g. not finding "1,2,3" in "11,2,31"). This can be achieved by using "][" as the separator so that all values are enclosed in the same way ("[1][2][3]" in "[11][2][31]"):

if str(S).replace(", ","][") in str(L).replace(", ","]["):
    print("found")
else:
    print("not found")

While this works on numeric values, it can still fail if the values are strings (which may contain any pattern including the string version of the sequence).

Alain T.
  • 40,517
  • 4
  • 31
  • 51
  • Just run a simple `performance` comparison between this and @Aven's and find out this is much faster: wondering what's the contributing factors. – Daniel Hao Jan 21 '21 at 16:10
  • I think it may be because the string approach relies on low level code for most of the work as opposed to the other ones that perform Python code in a loop (including generating list/tuples for subsets). BTW I change the string strategy condition (the previous one was missing the enclosing brackets) – Alain T. Jan 21 '21 at 21:29
0

Just out of curiosity, I've run a small performance comparison to see which one is faster for larger list (over 1+ million numbers). Here is the results:

import time

def list_contains(S, L):
    ''' check if S in in L - list of integers'''
    
    n = len(S)
    return any(S == L[i:i + n] for i in range(len(L)-n + 1))

# @AlainT version
def list_in_list(S, L):
    if tuple(S) in zip(*(L[i:] for i in range(len(S)))):
        return f'True'
    
    return f'False'




if __name__ == '__main__':
    test_list = L = list(range(1, 1_000_000))

    start_time = time.time()
    S = [567_899, 567_900, 567_901]
    
    list_contains(S, L)     # 0.1557  ** use any(..) from @Anoymous's got almost same results
    #list_in_list(S, L)     # 0.0528

    print('....%s seconds', (time.time() - start_time))
    
Daniel Hao
  • 4,922
  • 3
  • 10
  • 23
0

Do this:

def contains(sarr,sseq):
    return sseq in sarr
arr = [1,2,3,4,4,5,7,8]
seq = [1,2,3]
print(contains(''.join(map(str, arr)),''.join(map(str, seq))))

notnotparas
  • 177
  • 1
  • 11