python list and sublist

2019-06-07 09:16发布

问题:

I have to check if list1 is contained in list2. It also should check if it appears in that order in the list as well. If it's true, it should return true and false if it doesn't.

def check(lst1, lst2):
for x in lst1:
    for y in lst2:
        xx = lst1.sort()
        yy = lst2
        if xx != yy:
            return False
        else:
            return True

I'm confusing myself with the for loops and also, I don't know where to go from here to fix my code. Pointers please?

example of what it should do:

  check([4,0],[9,1,4,6,8,9])
  True
  check([1,2],[2,3,1])
  False

回答1:

I thought the problem was begging to be solved recursively, so I did:

def check(needle, haystack):
  if not needle:
      return True
  try:
    offset = haystack.index(needle[0])
    return check(needle[1:], haystack[offset+1:])
  except:
    return False

Edit:

Brief explanation:

First we check if the list we're looking for is empty (this is important once we start calling ourselves), since all lists have the empty list inside it, we return True. Then we try finding the first item of the list we're looking for in the list we're looking at. If we find it, we then call the function again, but change the arguments a bit: we already looked at the first item of the 'needle' and saw it in the 'haystack'. So now we need to check if the remainder of 'needle' is in the remainder of 'haystack'. So we call the function again only with the remainder of both lists. The remainder of needle is everything but the first element, and the remainder of haystack is all items after the one we found. If we get to a point where the first list is empty, it means we found it in the haystack. If we get an exception, what we were looking for wasn't found, so we return False, which bubbles up the call stack and gets returned.



回答2:

You could start with something like:

set(lst1).issubset(lst2)

to see if lst1 is contained within lst2 ignoring order. If it passes the test that one list is contained within the other, then you could do something like:

ii = lst2.index(lst1[0])
if lst2[ii:ii+len(lst1)] == lst1:
   return True
else:
   return False

Originally I stated that the first check was irrelevant given the second, although you'd have to properly handle the ValueError if the first element of lst1 is not in lst2.

Edit: Just as a side note, I compared a version of my code vs yan's and mine is significantly faster under almost all use cases, especially if len(lst1) is larger (up to 200x speedup vs yan's implementation). Give it a try with the timeit module.

def check(lst1,lst2):
    try:
        ii = lst2.index(lst1[0])
    except ValueError:
        return False

    if lst2[ii:ii+len(lst1)] == lst1:
        return True
    else:
        return False 

As an explanation of how it works ii = lst2.index(lst1[0]) finds the index in lst2 that matches the first element of lst1. If that item is missing from lst2 it catches the ValueError and returns False. If that element does exist, lst2[ii:ii+len(lst1)] == lst1 compares all of lst1 vs the sublist of lst2 starting from the matched element and taking the next len(lst) elements.



回答3:

>>> a=[9,1,4,6,8,9]
>>> by_twos=zip(a, a[1:])
>>> by_twos
[(9, 1), (1, 4), (4, 6), (6, 8), (8, 9)]
>>> (4,6) in by_twos
True