0

I am not sure if this question has been asked before but I couldn't find anything similar from the question list. I would like to check if a list has a set of three values in a certain order. For example, I would like to check if an int list has a set of values 1, 2, 3 anywhere within that list. The length of the list is unknown and the list cannot be sorted.

Example:

Values to check: 1, 2, 3 (in this order)
Example of a list = [1, 1, 2, 3, 1]

This is what I have tried so far.

list1 = [1, 1, 2, 3, 1]
list2 = [1, 1, 4, 3, 1, 2, 1]

def checkValue:
    for i in range (0, len(nums)):            
        if (nums[i+2] - nums[i+1] == nums[i+1] - nums[i]) == 1:
            return True           

    return False

list1 --> return True list2 ---> IndexError: list index out of range

EDIT: Thanks to those who answered and thank you for the list to the sublist question. I never thought that the set of integers can be considered as a sublist and use it to compare to a larger list.

Cryssie
  • 3,047
  • 10
  • 54
  • 81

4 Answers4

1

i + 2 is too large in the loop body, nums doesn't have that many elements. Fix it like this:

if i + 2 < len(nums) and (nums[i+2] - nums[i+1] == nums[i+1] - nums[i]) == 1:
    ...
pts
  • 80,836
  • 20
  • 110
  • 183
  • 1
    Or if you don’t do anything else in your loop that may require you to get to the end, you could just change the range to be `range(len(nums) - 2)`. – poke Sep 26 '13 at 10:29
1

It looks like you're searching a sequence in a list.

You can just compare parts of the list with the sequence.

def find_sequence_in_list(list_to_check, values):
    for i in range (len(list_to_check) - len(values) + 1):
        #print(list_to_check[i:i + len(values)])
        if list_to_check[i:i + len(values)] == values:
            return True

    return False

values = [1, 2, 3]
data1 = [1, 1, 2, 3, 1]
data2 = [1, 1, 4, 3, 1, 2, 1]

print(find_sequence_in_list(data1, values))
print(find_sequence_in_list(data2, values))

Uncomment the print to see what's happening.

Matthias
  • 12,873
  • 6
  • 42
  • 48
0

You can use tuple comparison directly, along with zip iteration (or itertools.izip if you prefer, for general iterables):

>>> def findin(values, nums):
...     t = tuple(values)
...     return any(T == t for T in zip(*(nums[i:] for i in xrange(values))))

Which gives for your examples:

>>> findin([1,2,3], [1,1,2,3,1])
True
>>> findin([1,2,3], [1, 1, 4, 3, 1, 2, 1])
False
val
  • 8,459
  • 30
  • 34
0

I'm thinking of using deque to the sublist comparison.

from collections import deque

def has_sublist(lst, sub):
    tmp_q = deque([], maxlen=len(sub))
    sub_q = deque(sub)
    for i in nums:
        if tmp_q == sub_q:
            return True
        else:
            tmp_q.append(i)
    return tmp_q == sub_q

The tmp_q has a max length of len(sub) (which is 3 in your example), it contains a sublist of list to search in.

Let's check if it works well:

>>> lst = [1, 1, 4, 3, 1, 2, 1]
>>> sub = [1, 2, 3]
>>> print has_sublist(lst, sub)
False

>>> lst = [1, 1, 4, 3, 1, 2, 3]
>>> print has_sublist(lst, sub)
True

>>> lst = [1, 2]
>>> print find(lst, sub)
False

>>> lst = [1, 2, 3]
>>> print has_sublist(lst, sub)
True

In this case, you have no need to worry about the IndexError.

Leon Young
  • 585
  • 2
  • 6
  • 14