首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >筛选字符法的优化运行时

筛选字符法的优化运行时
EN

Code Review用户
提问于 2014-11-07 18:43:33
回答 4查看 81关注 0票数 5

我试图在一个非常大的语料库上运行下面的方法,并且我需要优化/减少这个方法的运行时间,因为它已经占用了大约6秒的时间来执行。

需求:

  1. 检查单词仅由字母、连字符和撇号组成。
  2. 单词的第一个字符必须是字母表
  3. 单词的最后字符必须是字母表或撇号。
  4. 严格不允许使用re库(regex)
代码语言:javascript
运行
复制
def delUnknownChar(w):
    wf = []
    for c in w:
        if (c == "'" or c == "-" or c.isalpha()):
            wf.append(c)

    w = "".join(wf)
    wf.clear()

    if (len(w) > 1):
        while(not w[0].isalpha()):
            w = w[1:]

        while (w[-1] == "-"):
            w = w[:-1]

        return w
    else:
        return None

string1 = delUnknownChar("-'test'-")
print(string1)

输出将被测试,上面的代码将花费大约5秒的时间运行。

如果我将代码的第2-7行改为这一行:

代码语言:javascript
运行
复制
w = "".join(c for c in w if c == "'" or c == "-" or c.isalpha())

运行时以某种方式增加了1秒。

有没有人有一个更好的想法或改进的优化方法来检查这一速度快得多?

EN

回答 4

Code Review用户

发布于 2014-11-07 22:11:12

可能的性能改进

  • w = w[:-1]可能效率低下,因为它要求对列表中的每个元素执行一个副本,减去一个。del w[-1]是删除列表最后一个元素的惯用方法。
  • isalpha对应的字符串中的字符可能比完全等于"'""-"的字符多。因此,在其他两个条件之前检查isalpha,您可能会注意到速度的提高。
  • 您可以创建一个包含isalpha"'""*"的所有值的表,然后检查该表中是否有一个字符。但是,我不认为它能给您带来显著的速度改进,除非您使用可能被优化的专用str方法(例如,replace)进行过滤。

风格

一些关于风格的注释:

  • 请不要在while条件下插入括号,这与Python指南(PEP8)背道而驰。
  • if也是如此。
票数 2
EN

Code Review用户

发布于 2014-11-07 22:56:04

w(不是w0.isalpha()):W= w1:

当执行到达这段代码时,所有非字母或-'的字符都已被删除。因此,与其检查not .isalpha,不如检查字符是-还是',这样会更有效:

代码语言:javascript
运行
复制
while w[0] == "'" or w[0] == '-':
    w = w[1:]

方法的名称不是很大。delUnknownChar听起来像是“删除未知字符”,但这并不能很好地描述该方法的功能。您的要求比仅仅删除字符要复杂得多。比如sanitize_text,或者normalize_input会更好。

变量名wwf不是很好:

  • letters而不是wf会更好
  • word而不是w会更好

有一个要求,你忘了包括在你的描述:字必须长于一个字符。

应该将需求添加为方法的docstring。

票数 1
EN

Code Review用户

发布于 2014-11-07 22:28:51

所有这些在很大程度上取决于您的输入,因此假设您有完整的Unicode输入,因此不能使用str.translate或任何其他基于C的函数,这可能要快得多(或者用另一种实现/语言重写),我首先要重写到:

代码语言:javascript
运行
复制
def delUnknownChar(w):
    w = [c for c in w if c == "'" or c == "-" or c.isalpha()]

    if len(w) == 0:
        return None

    for i in range(len(w)):
        if w[i].isalpha():
            w = w[i:]
            break

    for i in range(len(w)-1, -1, -1):
        if w[i] != "-":
            w = w[:i+1]
            break

    return "".join(w)

因此,首先查找有效范围,然后执行下标一次,并且只进行一次到字符串的转换。恐怕不算太快。

另一种尝试是做同样的事,但更根本地避免不必要的转换:

代码语言:javascript
运行
复制
def deleteUnknownCharacters(word):
    l = len(word)

    start = None
    for i in range(l):
        if word[i].isalpha():
            start = i
            break

    if start == None:
        return None

    end = None
    for i in range(l-1, -1, -1):
        c = word[i]
        if c == "'" or c.isalpha():
            end = i
            break
        elif i <= start:
            break

    if start == None:
        return None

    result = [c for c in word[start:end+1] if c == "'" or c == "-" or c.isalpha()]

    if len(result) == 0:
        return None

    return "".join(result)

这可能会更快,取决于您的输入,否则在某种程度上与我所能知道的是相等的。

票数 0
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/69184

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档