当前位置: 首页 > 面试题库 >

Python字符串处理优化

戈嘉慕
2023-03-14
问题内容

因此,最近我一直在制作python脚本,用于从大型文本文件(> 1
GB)中提取数据。问题基本上可以归结为从文件中选择文本行,然后从某个数组中搜索字符串以查找字符串(此数组中可以包含多达1000个字符串)。这里的问题是我必须找到该字符串的特定出现,并且该字符串在该文件中可能出现无数次。同样,需要一些解码和编码,这另外会降低脚本速度。代码看起来像这样:

strings = [a for a in open('file.txt')]

with open("er.txt", "r") as f:
    for chunk in f:
        for s in strings
            #do search, trimming, stripping ..

我的问题是:有没有办法对此进行优化?我尝试了多处理,但是它没有多大作用(或者至少没有实现它的方式)。这里的问题是这些块操作不是独立的,并且strings列表可能会在其中之一发生更改。任何优化都将有所帮助(字符串搜索算法,文件读取等),我在循环中断方面已尽我所能,但运行速度仍然很慢。


问题答案:

如果您确切知道字符串是如何以二进制(ASCII,UTF-8)编码的,则可以一次mmap
整个 文件存入内存;它的行为就像will 将获得的大bytearray/bytes(或str在Python
2中)file.read();那么mmap可以用str正则表达式(Python 2)或bytes正则表达式(Python
3)搜索这样的对象。

mmap是许多操作系统上最快的解决方案,因为只读映射意味着操作系统可以在页面准备就绪时自由地映射它们。不需要交换空间,因为数据由文件支持。操作系统还可以直接将缓冲区缓存中的数据映射为零拷贝,从而在裸读上实现双赢。

例:

import mmap
import re

pattern = re.compile(b'the ultimate answer is ([0-9]+)')
with open("datafile.txt", "rb") as f:
    # memory-map the file, size 0 means whole file
    mm = mmap.mmap(f.fileno(), 0, prot=mmap.PROT_READ)

    # PROT_READ only on *nix as the file is not writable
    for match in pattern.finditer(mm):
        # process match
        print("The answer is {}".format(match.group(1).decode('utf8')))

    mm.close()

现在,如果datafile.txt包含文本:

the ultimate answer is 42

沿着1 GB数据的某个地方,该程序将是最快推出的python解决方案之一:

The answer is 42

请注意,该参数pattern.finditer还接受startend参数,这些参数可用于限制尝试匹配的范围。

正如van_pozdeev所指出的,这需要1
GB的可用虚拟地址空间来映射1 GB的文件(但不一定是1
GB的RAM),这在32位进程中可能很困难,但几乎可以肯定地认为是“没有问题的”在64位操作系统和CPU上。在32位进程上,该方法仍然有效,但是您需要将大文件映射为较小的块-
因此,操作系统和处理器的位确实很重要。



 类似资料:
  • Pandas 提供了一系列的字符串函数,因此能够很方便地对字符串进行处理。在本节,我们使用 Series 对象对常用的字符串函数进行讲解。 常用的字符串处理函数如下表所示: 函数名称 函数功能和描述 lower() 将的字符串转换为小写。 upper() 将的字符串转换为大写。 len() 得出字符串的长度。 strip() 去除字符串两边的空格(包含换行符)。 split() 用指定的分割符分割

  • StringBuffer 是一个字符串拼接工具,和java中的StringBuilder类似。对于那些需要大量的字符串连接的时候,用 StringBuffer 更高效一些。它实现了以下API: class StringBuffer { public function __construct($str); public function isEmpty(); publi

  • 字符串在我们平常的Web开发中经常用到,包括用户的输入,数据库读取的数据等,我们经常需要对字符串进行分割、连接、转换等操作,本小节将通过Go标准库中的strings和strconv两个包中的函数来讲解如何进行有效快速的操作。 字符串操作 下面这些函数来自于strings包,这里介绍一些我平常经常用到的函数,更详细的请参考官方的文档。 func Contains(s, substr string)

  • 函数 说明 Series.str.capitalize() 将 Series / 索引中的字符串转换为大写。 Series.str.cat([others, sep, na_rep, join]) 使用给定的分隔符连接 Series / 索引中的字符串。 Series.str.center(width[, fillchar]) 用附加字符填充 Series / 索引中字符串的左侧和右侧。 Seri

  • 在 Bash 脚本中可以调用字符串处理工具 awk 来替换内置的字符串处理操作。 样例 10-6. 使用另一种方式来截取和定位子字符串 #!/bin/bash # substring-extraction.sh String=23skidoo1 # 012345678 Bash # 123456789 awk # 注意不同字符串索引系统: # Bash 中第一个字符

  • 在DOS中,字符串是一个有序的字符集合,比如:。 编号 字符串操作 描述 1 创建字符串 字符串可以通过以下方式在DOS中创建。 2 空字符串 空的字符串 3 字符串插值 字符串插值是一种通过将常量,变量,文字和表达式中的值包含在字符串文字中来构造新的字符串值的方法。 4 字符串连接 可以使用运算符连接两个字符串,一个字符串和一个字符,或者两个字符。 以下是一个简单的例子,展示了如何使用字符串连接