Reputation: 51
Let's say I have 2 lists:
a = [6,7,8,9,10]
b = [1,3,4,6,7,8,9,10]
I have a function that is used to find out if list a can be found in list b. If it is found, then it returns True. In my case it should return True because list a can be found at the end of list b. List a never changes and always contains the same numbers, whereas list b accepts numbers from the user and then uses sorted()
method to sort numbers in ascending order. I should also add that the order does matter.
I have searched around and could find a subset method, which looks like this: set(a).issubset(set(b)))
as well as using in
method. Both of them did not work for me.
UPDATE:
Using set(a).issubset(set(b)))
for some reason always returns True. For example, if
a = [1,1]
and b = [0,1,2,3,4,5]
then using subset method returns True, even though 1,1 cannot be found in b. I'm not looking if 1 is inside the list, I'm looking if 1,1 is inside the list.
Using in
method when
a = [6,7,8,9,10]
b = [1,3,4,6,7,8,9,10]
returns False.
Upvotes: 0
Views: 637
Reputation: 103844
You do not need to loop over each and every index. Just find the first element and then see of the remainder elements match.
You could do something along these lines:
a = [6,7,8,9,10]
b = [1,3,4,6,7,8,9,10]
def liAinliB(a, b):
try:
ind=b.index(a[0])
except ValueError:
return False
return b[ind:ind+len(a)]==a
print(liAinliB(a, b))
Upvotes: 0
Reputation: 304175
If the values in a
and b
happen to be in the range 0-255, you can use this trick
>>> a = [6,7,8,9,10]
>>> b = [1,3,4,6,7,8,9,10]
>>> bytearray(a) in bytearray(b)
True
Upvotes: 1
Reputation: 1927
Something you find useful
idx = -1
notfound = False
for index, item in enumerate(b):
if item == a[0]:
idx = index
if idx == -1:
notfound = True
for i in xrange(idx, len(a) + idx):
if len(b) <= i or a[i - idx] != b[i]:
notfound = True
print "Not found: ", notfound
Upvotes: 0
Reputation: 70602
You didn't say how important speed was. So I'd wrap the functionality in a class, so that you can hide the complications from the rest of your code if you need to get fancier later. Since
List a never changes and always contains the same numbers
it makes sense to pass a
to the class constructor. Here's one way:
class ASearcher:
def __init__(self, a):
self.a = a
def isin(self, b):
a = self.a
a0 = a[0]
lena = len(a)
i = 0
try:
while 1:
j = b.index(a0, i) # raises ValueError if not found
if a == b[j: j+lena]:
return True
i = j+1 # start search over 1 position later
except ValueError:
return False
Then, e.g.,
asearch = ASearcher([6,7,8,9,10])
print asearch.isin([1,3,4,6,7,8,9,10])
prints True
.
There is no function in the standard library to do what you want here, so you need to roll your own. The class above implements a method that does the searching, in B, for the first element of A, "at C speed". It will probably be "fast enough" - maybe ;-)
Upvotes: 2
Reputation: 353059
If I understand you, you're interested in knowing whether a
is a contiguous subsequence of b
. So:
>>> a = [6,7,8,9,10]
>>> b = [1,3,4,6,7,8,9,10]
>>> any(b[i:i+len(a)] == a for i in range(len(b)-len(a)+1))
True
This isn't the most efficient approach, but it'll often be fast enough in practice.
Upvotes: 0
Reputation: 86188
Here is a brute force way:
a = [6,7,8,9,10]
b = [1,3,4,6,7,8,9,10]
def check_if_in_list(a, b):
for i in xrange(len(b) - len(a) + 1):
if a == b[i : i + len(a)]:
return True
return False
Result:
>>> check_if_in_list(a, b)
True
Upvotes: 0