I want to find all 5-digit strings, for which
l0=["123","567","451"]
l1=["234","239","881"]
l2=["348","551","399"]
should thus yield: ['12348', '12399']
.
I have therefore written a function is_successor(a,b)
that tests if a and b overlap:
def is_successor(a:str,b:str)->bool:
"""tests if strings a and b overlap"""
return a[1:]==b[:2]
I can then achieve my goal by writing this nested loop/check structure, that basically appends back to front strings and resulting in all valid strings:
pres=[]
for c in l2:
for b in l1:
if is_successor(b,c):
for a in l0:
if is_successor(a,b):
pres.append(a[0]+b[0]+c)
pres
l2
-> l0
because in my original data the lists become longer, the lower the index and thus I can filter out more cases early this way.l0,l1,l2
and checking the succession of all items a,b,c
simultaneously would work but it test way more unnecessary combinations than my current construct does.Question:
How can this nested loop and conditional checking call be abstracted? Is there a pythonic way to capture the repetition of for
-> is_successor()
?
A larger input might be:
primes = [2, 3, 5, 7, 11, 13, 17]
lsts=[
[
str(j).zfill(3)
for j in range(12,988)
if not j%prime
]
for prime in primes
]
I would use itertools product to define a function that will perform the check annd append the data:
import itertools
def get_list(l1,l2):
#THIS FUNCTION WILL TEST ALL THE PRODUCTS AND RETURN ONLY THE CORRECT ONES
return [a+b[2:] for a,b in list(itertools.product(l1,l2)) if a[1:] == b[:2]]
then you can nest the function like this:
get_list(l0,get_list(l1,l2))
you will get the expected result: ['12348', '12399']
EDIT: for a long list use reduce.
let s call l
the list of list of inputs. In your specific case l = list([l0,l1,l2])
Reverse the list to apply from the end till the beginning l.reverse()
and the final code:
from functools import reduce
reduce(lambda x,y:get_list(x,y),l)
Note: in this case you want to change the inputs of the "get_list" function as it will go l2 then l1 then l0.Just change the def of get_list like this: def get_list(l2,l1)