Home>

There are 2 lists:

a= ["hello", "order", "123", "100", "pcs", "345", "500bays", "and", "678", "700m"]
b= ["pcs", "bays", "m"]

It is necessary to check if the element of the first list contains an element from the second list. But if an element from the first list is equal to an element from the second list, then we do not add it to the new list. As a result, you need to get a list:

['500bays', '700m']

Do this after 2 cycles or is there an easier way out?

  • Answer # 1

    It depends on what you call a loop. Here instead of two nestedfortwofilterwithlambda, but in fact it is still a loop in a loop with complexityO (n ^ 2):

    print (list (filter (lambda x: any (filter (lambda y: y in x and x!= y, b)), a)))
    

    Conclusion:

    ['500bays', '700m']
    

    P.S. By the way, MaxU is right -you never know where the letter "m" can be found inside the word. It's probably better to really use regulars, or at least check not throughinand afterendswithif a string frombmust be at the end of the line, and that before that comes the number can also be checked without regulars throughisdigit:

    print (list (
        filter (lambda x: any (
            filter (lambda y: x.endswith (y) and
                          x [: -len (y)]. isdigit () and
                          x!= y,
                   b)
            ), a)
        ))
    
  • Answer # 2

    In my opinion, this task should be solved using regular expressions. Surely you will have words in your real list that contain the letter "m" and which have nothing to do with meters.

    import re
    a= ["hello", "thrill!", "order", "123", "100", "pcs", "345", "500 bays", "and", "678", "700m"]
    b= ["pcs", "bays", "m"]
    pat= r "\ d + \ s * (?: {})". format ("|" .join (b))
    res= [x for x in a if re.search (pat, x)]
    

    result:

    In [522]: res
    Out [522]: ['500bays', '700m']
    
  • Answer # 3

    completely without loops, it turned out to collect such a clumsy, but working construction:

    import pandas as pd
    arr= pd.Series (a)
    expr= '|' .join (b)
    c= arr [arr.str.contains (expr, regex= True) &
    ~ arr.str.fullmatch (expr)]. to_list ()
    # ['500bays', '700m']
    
  • Answer # 4

    Well, if you want, you can get by with one cycle, though I'm not sure that it would be better this way:

    a= ['hello', 'order', '123', '100', 'pcs', '345', '500bays', 'and', '678', '700m']
    b= ['piece', 'bay', 'm']
    c= [* filter (lambda x: any (i in x for i in b if i!= x), a)] # ['500 bays', '700m']
    
  • Answer # 5

    Yes, do it after 2 cycles. If you want to shorten the code, you can use.

    Example:

    a= ['hello', 'order', '123', '100', 'pcs', '345', '500bays', 'and', '678', '700m']
    b= ['piece', 'bay', 'm']
    d= [x for y in b for x in a if y in x and x!= y]
    print (d)
    

    stdout:

    ['500bays', '700m']