【发布时间】:2012-12-17 13:57:41
【问题描述】:
我有一个名称列表,用于从目标字符串列表中提取。例如:
names = ['Chris', 'Jack', 'Kim']
target = ['Chris Smith', 'I hijacked this thread', 'Kim','Christmas is here', 'CHRIS']
output = ['Chris Smith', 'Kim', 'CHRIS']
所以到目前为止的规则是:
- 不区分大小写
- 无法匹配部分单词('ie Christmas/hijacked 不应该匹配 Chris/Jack)
- 字符串中的其他单词都可以,只要根据上述条件在字符串中找到名称即可。
为此,另一位 SO 用户在 this thread 中建议了此代码:
[targ for targ in target_list if any(re.search(r'\b{}\b'.format(name), targ, re.I) for name in first_names)]
到目前为止,这非常准确,但是考虑到名称列表的长度约为 5,000,目标列表的长度范围为 20-100 行,其中一些字符串最长为 30 个字符,因此运行速度非常慢。
关于如何提高性能的任何建议?
解决方案:两个基于正则表达式的解决方案都遭受了溢出错误,所以很遗憾我无法测试它们。有效的解决方案(来自@mglison 的回答)是:
new_names = set(name.lower() for name in names)
[ t for t in target if any(map(new_names.__contains__,t.lower().split())) ]
这将性能从 15 秒提高到不到 1 秒巨大。
【问题讨论】:
-
你的名字都是单字吗?
-
呃-哦。 @DSM 即将推出
str.split+set解决方案或类似的解决方案。 (可能用timeit显示它可以有多快;-) -
@mgilson:伙计,我需要一些新技巧。每个人都喜欢我的旧人..
-
@DSM -- 他们是好把戏。很难想象你能想出更好的(尽管,如果你确实想出了更好的,请发布它们,这样我就可以开始在我的答案中使用它们并继续获得支持,而无需实际开发任何类型个人创造力:-p)