【问题标题】:Python performance with replace that seldom replaces很少替换的 Python 性能
【发布时间】:2020-07-29 17:45:58
【问题描述】:

我正在使用 python 3.6 将字符串列表作为制表符分隔文件编写

数据中存在标签的情况很少见,但假设是可能的。如果是这样,我需要用空格替换它们。我喜欢这样:

row = [x.replace("\t", " ") for x in row]

问题是,这一行大约占了整个程序运行时间的 1/4,而且它几乎从来没有真正做任何事情。

有没有更快的方法从我的数据中清除标签页?

有没有办法利用它可能没有任何标签的事实?

我尝试过使用字节而不是字符串,这没有任何区别。

【问题讨论】:

    标签: python python-3.x text replace


    【解决方案1】:

    我尝试了各种方法,最快的方法是在存在选项卡的索引处执行条件替换

    def testReplace(sList):
        return [s.replace("\t"," ") for s in sList]
    
    noTabs  = str.maketrans("\t"," ")
    def testTrans(sList):
        return [s.translate(noTabs) for s in sList]
    
    def joinSplit(sList):
        return "\n".join(sList).replace("\t"," ").split("\n")
    
    def conditional(sList):
        result = sList.copy() # not needed if you intend to replace the list
        for i,s in enumerate(sList):
            if "\t" in s:
                result[i] = s.replace("\t"," ")
        return result
    

    性能检查:

    from timeit import timeit
    count   = 100
    strings = ["Hello World"*10]*1000  # ["Hello \t World"*10]*1000
    
    t = timeit(lambda:testReplace(strings),number=count)
    print("replace",t)   
    
    t = timeit(lambda:testTrans(strings),number=count)
    print("translate",t) 
    
    t = timeit(lambda:joinSplit(strings),number=count)
    print("joinSplit",t) 
    
    t = timeit(lambda:conditional(strings),number=count)
    print("conditional",t)
    

    输出:

    # With tabs
    replace     0.03365320100000002
    translate   0.08165113099999993
    joinSplit   0.027709890000000015
    conditional 0.007067911000000038
    
    # without tabs
    replace     0.015160736000000008
    translate   0.07439537500000004
    joinSplit   0.017001820000000056
    conditional 0.0065534649999999806
    

    【讨论】:

    • 谢谢!在我的机器上,我的数据很有趣。使用字符串,连接比条件连接稍快。使用字节,条件比原始替换慢得多,并且连接与字符串连接大致相同(即比替换快得多)。我现在将切换到加入,除非弹出更好的答案。
    • 对我来说,这甚至更快: if "\t" in "".join(row): row = "\n".join(row).replace("\t", " ").split("\n")
    【解决方案2】:

    在性能问题上未经测试,但我会使用知道包含新行或分隔符的字段并自动引用它们的 csv 模块:

    import csv
    
    with open(filename, 'w', newline='') ad fd:
        wr = csv.writer(fd, delimiter='\t')
        ...
            wr.writerow(row)
    

    【讨论】:

    • 谢谢,但我不能使用 csv,因为我特别不希望它插入引号。
    猜你喜欢
    • 2022-01-14
    • 2016-02-25
    • 2022-12-13
    • 2011-04-07
    • 1970-01-01
    • 2021-09-15
    • 1970-01-01
    • 1970-01-01
    • 2016-03-14
    相关资源
    最近更新 更多