根据多个可能的deminiters拆分字符串,但保留分隔符

时间:2016-06-29 18:44:28

标签: python

我正在清理地址。我希望在特定词语(大道,大街,道路,地点等等)之后去除所有内容。

我正在考虑做这样的事情,但我相信这会在这个词之前返回所有内容。这意味着" 1第一条大道"将首先返回" 1"。

我如何追加这个(或者以不同的方式做到这一点?),以便将所有内容返回到AND包含模式词?

patterns = ["ave", "avenue", "road", "street" etc etc etc]
reduce(lambda s, pat: s.split(pat, 1)[0], patterns, string)

4 个答案:

答案 0 :(得分:2)

我认为这就是你想要的。

pattern = ['ave', 'street', 'road']
address = 'Imaginary ave, Fantasy Island'

for i in pattern:
    if i in address:
        print address[:address.find(i) + len(i)]

或者如果有地址列表

print [address[:address.find(i) + len(i)] for i in pattern if i in address]

答案 1 :(得分:1)

有几种方法可以实现这一目标。如果reduce此处有一个签名,这是将答案保持在lambda范围内的一种方式:

patterns = ["ave", "avenue", "road", "street"]
string = 'queen ave west'
reduce(lambda s, pat: s[:s.find(pat)+len(pat)] if s.find(pat) > 0 else s, patterns, string)

但是更好的解决方案可能是通过使用正则表达式。这将所有可能的“模式”组合成一个正则表达式,并通过python的正则表达式引擎运行整个事件:

import re
patterns = ["ave", "avenue", "road", "street"]
regex = r'(.*)(' + '|'.join(patterns) + r')(.*)'
string = 'queen ave west'
re.sub(regex, r'\1\2', string)

如果你将它应用于多个地址,你可以先编译正则表达式然后在你要清理的每个地址上使用编译的正则表达式来优化代码:

import re

patterns = ["ave", "avenue", "road", "street"]
regex = re.compile(r'(.*)(' + '|'.join(patterns) + r')(.*)')
strings = ['queen ave west', 'should stay the same']
sanitized_strings = (regex.sub(r'\1\2', string) for string in strings)

现在sanitized_strings包含已清理的字符串版本。您可以使用for循环遍历sanitized_strings并打印它们或执行任何其他操作。请注意,正则表达式的设计方式是,如果patterns中没有单词,则整个字符串将与第一个组匹配。因此,如果没有任何单词存在,它将保持字符串不变,就像您要求的那样。

我不确定那些是你正在寻找的确切语义。例如,你真的想要'皇后大道'回归'皇后大道'。还要注意到目前为止所提到的所有解决方案都不考虑其中一个模式是否在街道名称中,如果您的模式包含缩写“st”或者例如在多伦多,那么很可能叫'大道路'。这些问题的答案取决于你想要达到的目标。

答案 2 :(得分:0)

这适用于在字符串中搜索特定的子字符串,我使用字符串index()方法(但是,正如其他用户指出的那样,有多种方法可以解决这个问题),这就是为什么有一个try / except块。如果找不到子字符串,index()方法将返回错误。

def strip_address(string):
    patterns = ["ave", "road", "street"]
    final_address = ''

    for pattern in patterns:
        try:
            if not string.index(pattern): continue

            # The tail-index of the pattern in the string
            last_index = len(pattern) + string.index(pattern)

            final_address = string[:last_index] # parsed address
            return final_address

        except ValueError:
            pass

<强>测试

string = "1 first street 213322"
> '1 first street'

string1 = "1023 sunset road Extra Text here"
> '1023 sunset road'

string2 = "23 applewood ave Apt.1241"
> '23 applewood ave'

答案 3 :(得分:0)

你可以用这种紧凑的方式

print reduce (lambda s,x : str(s.split(x)[0]) if (str(s.split(x)[0]) == s) else str(s.split(x)[0]) + x,patterns)

完整示例

patterns = ["ave", "ave", "road" ]
string = "1 first avenue"
patterns.insert(0,string)
print reduce (lambda s,x : str(s.split(x)[0]) if (str(s.split(x)[0]) == s) else str(s.split(x)[0]) + x,patterns)

我们的想法是我们使用reduce进行过滤以了解何时读取分隔符字