Python: find a list within members of another list(in order)

前端 未结 9 2063
栀梦
栀梦 2020-12-03 10:40

If I have this:

a=\'abcdefghij\'
b=\'de\'

Then this finds b in a:

b in a => True

Is there a way of doi

相关标签:
9条回答
  • 2020-12-03 11:13

    Not sure how complex your application is, but for pattern matching in lists, pyparsing is very smart and easy to use.

    0 讨论(0)
  • 2020-12-03 11:19

    Don't know if this is very pythonic, but I would do it in this way:

    def is_sublist(a, b):
        if not a: return True
        if not b: return False
        return b[:len(a)] == a or is_sublist(a, b[1:])
    

    Shorter solution is offered in this discussion, but it suffers from the same problems as solutions with set - it doesn't consider order of elements.

    UPDATE:
    Inspired by MAK I introduced more concise and clear version of my code.

    UPDATE: There are performance concerns about this method, due to list copying in slices. Also, as it is recursive, you can encounter recursion limit for long lists. To eliminate copying, you can use Numpy slices which creates views, not copies. If you encounter performance or recursion limit issues you should use solution without recursion.

    0 讨论(0)
  • 2020-12-03 11:19

    I suspect there are more pythonic ways of doing it, but at least it gets the job done:

    l=list('abcdefgh')
    pat=list('de')
    
    print pat in l # Returns False
    print any(l[i:i+len(pat)]==pat for i in xrange(len(l)-len(pat)+1))
    
    0 讨论(0)
  • 2020-12-03 11:20
    >>>''.join(b) in ''.join(a)
    
    True
    
    0 讨论(0)
  • 2020-12-03 11:23

    So, if you aren't concerned about the order the subset appears, you can do:

    a=list('abcdefghij')
    b=list('de')
    set(b).issubset(set(a))
    
    True
    

    Edit after you clarify: If you need to preserve order, and the list is indeed characters as in your question, you can use:

    ''.join(a).find(''.join(b)) > 0
    
    0 讨论(0)
  • 2020-12-03 11:28

    I think this will be faster - It uses C implementation list.index to search for the first element, and goes from there on.

    def find_sublist(sub, bigger):
        if not bigger:
            return -1
        if not sub:
            return 0
        first, rest = sub[0], sub[1:]
        pos = 0
        try:
            while True:
                pos = bigger.index(first, pos) + 1
                if not rest or bigger[pos:pos+len(rest)] == rest:
                    return pos
        except ValueError:
            return -1
    
    data = list('abcdfghdesdkflksdkeeddefaksda')
    print find_sublist(list('def'), data)
    

    Note that this returns the position of the sublist in the list, not just True or False. If you want just a bool you could use this:

    def is_sublist(sub, bigger): 
        return find_sublist(sub, bigger) >= 0
    
    0 讨论(0)
提交回复
热议问题