문제

Assume that I have a string like this:

x = "Romeo and Juliet"

I would like to separate the two names "Romeo" and "Juliet" by recognizing the keyword "and", for example creating an output list:

y = ["Romeo", "Juliet"]

What it matters is that however the word "and" is written (examples: AND, And, aNd, anD etc.) shouldn't bring confusion to the interpreter that will understand it means "and" and will split the two words anyway. I have sorted with a horrible solution like this:

y = []
i = 0
tmpString = ""
while x[i] != " ":
    tmpString = tmpString + x[i]
    i += 1

i += 1
if x[i:i+3] == 'and' or x[i:i+3] == 'aNd': #and all the other cases...
y.append(tmpString)
tmpString = ""
i += 4
while i < len(x):
    tmpString = tmpString + x[i] 
y.append(tmpString)

Of course I could make the algorithm a bit more complex (to take into account the cases when there are more than just two names, when it's a "or" rather than an "and" etc.) but I don't really like the idea of iterating so many times through the string. Moreover I'm very new to Python, and I didn't understand how to use these modules and methods such as "evaluate", or "parsing" etc. Does anyone have any suggestion to make a nicer and more flexible algorithm?

도움이 되었습니까?

해결책

You can use re module:

>>> import re
>>> re.split(r'\s+AND\s+', 'Romeo AnD Juliet', flags=re.I) # re.I tells Python to ignore case
['Romeo', 'Juliet']

If you want to split on AND or OR, then you can change the regexp a bit:

>>> re.split(r'\s+(?:AND|OR)\s+', 'Romeo Or Juliet', flags=re.I)
['Romeo', 'Juliet']

다른 팁

You can use regular expressions to do this. Here is an example:

>>> import re
>>> import string
>>> x = "Romeo and Juliet"
>>> map(string.strip, re.split(r"\bAND\b", x, flags=re.I))
['Romeo', 'Juliet']

Try this comprehension:

>>> x = "Romeo and Juliet"
>>> y = [word for word in x.split() if word.lower() != "and"]
>>> y
['Romeo', 'Juliet']
>>> x = "Romeo aND Juliet"
>>> y = [word for word in x.split() if word.lower() != "and"]
>>> y
['Romeo', 'Juliet']

The key is applying lower() when you compare your word to the key. This normalizes what you might find into a form you'd can expect. So even if key = "aND" or key = "AnD", key.lower() = "and" regardless.

Just for completeness, you could do this with functions other than lower() and end up with an equivalent solution so long as your key matches. Some examples:

  • y = [word for word in x.split() if word.title() != "And"]

  • y = [word for word in x.split() if word.upper() != "AND"]

Some notes:

  • As Sunny Nada pointed out, this approach gives less than ideal results if the names ahve spaces (x = "Joe Smith and Tom" >>> ["Joe", "Smith", "Tom"]). If this is not what you want, you'll need a more robust method (like re)

  • To make your approach work you could change if x[i:i+3] == 'and' or x[i:i+3] == 'aNd': to if x[i:i+3] in ["and", "AND", "aNd", ...etc]:. This approach is typically considered better form for testing multiple values (or conditions). Alternatively, you could use the if statement that I use in my comprehension and get similar results (if x[i:i+3].lower() == "and":)

One final suggestion (mostly for fun) which will work with multi-word names and avoids re

>>> y = map(lambda s: s.strip(), map(lambda s: s.title(), x.lower().split('and')))
>>> y
['Romeo', 'Juliet']

Note that this is probably an abuse of map() and lambda functions

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top