How can I get a list of all possible matches in be

2019-07-15 04:04发布

问题:

I have the string "I like lettuce and carrots and onions" in Python.

I thought I could get the following matches ["I like lettuce", "I like lettuce and carrots", "I like lettuce and carrots and onions"] by using a regex like .* and. (The regex should match any character up to " and".)

However, using the greedy version (.* and) gives me only the last match, and using the non-greedy version (.*? and) gives me only the first match.

How can I get all three matches?

(I do not need a regex solution.)

回答1:

For fun, use the string partition method in Python 3. It searches a string for a substring, and returns a 3-tuple. When there's a match, it's

(string before the match, the match, string after the match)

Once you're used to it, it's very pleasant - no indexing needed, and it makes it easy to get the right results. So while this code is longer than some other ways, you should be able to reason about it easily:

def findallprefix(s, sep):
    sofar = ""
    while True:
        head, matched, s = s.partition(sep)
        if matched:
            assert matched == sep
            sofar += head
            yield sofar
            sofar += matched
        else:
            break

s = "I like lettuce and carrots and onions and dressing."
for match in findallprefix(s, " and"):
    print(repr(match))

which prints

'I like lettuce'
'I like lettuce and carrots'
'I like lettuce and carrots and onions'


回答2:

I wouldn't use an re at all: What is wrong with:

p = "I like lettuce and carrots and onions and dressing.".split("and")

which gives you a list from which you construct the desired strings.



回答3:

You can use simple splitting and construct strings without an expensive regex:

s = "I like lettuce and carrots and onions and dressing."

splitted = s.split('and')
for x in range(1, len(splitted)):
    print('and'.join(splitted[:x]))

# I like lettuce
# I like lettuce and carrots                                  
# I like lettuce and carrots and onions                        

If you need result in a list, go for a list-comprehension:

>>> s = "I like lettuce and carrots and onions and dressing."
>>> splitted = s.split('and')
>>> ['and'.join(splitted[:x]) for x in range(1, len(splitted))]
['I like lettuce ', 'I like lettuce and carrots ', 'I like lettuce and carrots and onions ']