Python 2:一行或非常紧凑的代码,用于检查几个字符串的“startswith”?

时间:2013-09-11 17:05:55

标签: python list

情景:

我有一个清单:

['item','place','thing']

我有一些字符串:

"item", "item1", "thing55", "place_C", "stuff", "junk5"

在上面,我希望前四个匹配,最后两个不匹配。 startswith函数最适合此检查。

(测试字符串“item”,“item1”等的列表不是python列表;它只是一组可能被检查的样本数据。但是,要与“item”匹配的字符串列表, “place”,“thing”是代码中的python列表。)

我可以遍历第一个列表并将字符串与startswith进行比较:

successVar = False
for s in myStrings:
    if (testString.startswith(s)): 
        successVar = True
        break
#  Now you would check successVar to decide if string matched

但在所有情况下,这并不一定最好。例如,假设这是if / elif结构的一部分:

if (testString == "hello"):
    # do something based on exact string match
elif (testString.endswith("!")):
    # do something if string ends with _one_ specific entity
elif <somehow, do the above comparison in here>
    # do something if string starts with any of the items in a list
else:
    # do something if string didn't match anything

我想我可以将整个检查包装在一个函数中,但我觉得可能有一种方法可以更容易或更简洁地使用内联代码。

这是否可以在没有功能的情况下完成?

由于

4 个答案:

答案 0 :(得分:10)

str.startswith()接受一组前缀:

>>> "item1".startswith(("item","place","thing"))
True

答案 1 :(得分:1)

您可以将正则表达式用于各种测试。正则表达式很容易“以”开头“,”以“结尾”,“完全匹配”或“包含”。您甚至可以指定匹配不区分大小写。您可以使用字典将正则表达式与要采取的每个操作相关联(应该是一个函数):

import re

def handle_item(text):
    print "handling item", text

def handle_place(text):
    print "handling place", text

def handle_thing(text):
    print "handling thing", text

match_dict = {"!$":          handle_thing,    # ends with !
              "(?i)^hello$": handle_place,    # case-insensitive exact match for hello
              "^@":          handle_item,     # begins with @
             }

test_string = raw_input("Enter a string to test: ")

for regex in match_dict:
    if re.search(test_string, regex):
        match_dict[regex](test_string)        # call function
        break

如果测试应按特定顺序执行,则可以使用collections.OrderedDict来提供(或者就此而言的元组列表)。此外,目前测试在找到一个匹配后停止;如果多个测试可以匹配,并且您希望处理所有测试,只需删除break

当然这只是处理一个项目...我将它放在一个函数中并为每个项目调用它,将项目拆分为自己的函数。

答案 2 :(得分:0)

可以使用csv来分解字符串,然后只需将tuple传递给str.startswith

import csv

check = ['item','place','thing']
items = '"item", "item1", "thing55", "place_C", "stuff", "junk5"'
match = [el for el in next(csv.reader([items], skipinitialspace=True)) if el.startswith(tuple(check))]
# ['item', 'item1', 'thing55', 'place_C']

答案 3 :(得分:0)

将允许的前缀列表加入到字符串中,以|分隔,例如:

pattern = "|".join(['item','place','thing'])

然后使用re.match()

strs = ["item", "item1", "thing55", "place_C", "stuff", "junk5"]
matching_strs = [s for s in strs if re.match(pattern, s)]

这会产生:

matching_strs
=> ['item', 'item1', 'thing55', 'place_C']

这也应该更快,然后建议其他方法,因为它只会查看strs中的任何字符串一次,并将其与所有允许的前缀“一次”进行比较,而不是一次一个

如果您在re.compile上使用pattern,您甚至可以加快速度。

警告:只有当允许的前缀不包含“re意义上的”特殊“字符时,这个简单的情况才有效,例如|.,{{1如果他们这样做,你必须先将它们转义,然后才能加入(