从字符串创建python字典的最佳方法是什么?
我有一个大文件,我将在其中解析大约1.9E8行 在每次迭代过程中,我将创建一个临时字典发送给另一个方法,它将提供我想要的输出 由于文件太大,我无法使用readlines()方法打开它 因此,我最后的办法是在解析过程中加快速度 我已经有了两个生成字典的选项optionB的性能优于optionA,我知道我可以试试正则表达式,但我不熟悉它。如果有更好的替代方案,我愿意听取意见 预期输入:从字符串创建python字典的最佳方法是什么?,python,regex,dictionary,Python,Regex,Dictionary,我有一个大文件,我将在其中解析大约1.9E8行 在每次迭代过程中,我将创建一个临时字典发送给另一个方法,它将提供我想要的输出 由于文件太大,我无法使用readlines()方法打开它 因此,我最后的办法是在解析过程中加快速度 我已经有了两个生成字典的选项optionB的性能优于optionA,我知道我可以试试正则表达式,但我不熟悉它。如果有更好的替代方案,我愿意听取意见 预期输入:“A@1:100;2:240;…:“输入可能更长,它可以有更多的组及其频率 预期输出:{'1':'100','2':
“A@1:100;2:240;…:“
输入可能更长,它可以有更多的组及其频率
预期输出:{'1':'100','2':'240'}
我愿意接受任何建议 解析行的正则表达式的快速示例:
>>> import re
>>> line = 'A@1:100;2:240'
>>> data = re.search(r'@(\d+):(\d+);(\d+):(\d+)',line).groups()
>>> D = {data[0]:data[1],data[2]:data[3]}
>>> D
{'1': '100', '2': '240'}
以下是一些时间安排:
import re
regex = re.compile(r'@(\d+):(\d+);(\d+):(\d+)')
def optionA(line):
_id, info = line.split("@")
data = {}
for g_info in info.split(";"):
k, v = g_info.split(":")
data[k] = v
return data
def optionB(line):
_id, info = line.split("@")
return dict(map(lambda i: i.split(":"), info.split(";")))
def optionC(line):
data = regex.search(line).groups()
return {data[0]:data[1],data[2]:data[3]}
line = 'A@1:100;2:240'
时代:
C:\>py -m timeit -s "import x" "x.optionA(x.line)"
100000 loops, best of 3: 3.01 usec per loop
C:\>py -m timeit -s "import x" "x.optionB(x.line)"
100000 loops, best of 3: 5.15 usec per loop
C:\>py -m timeit -s "import x" "x.optionC(x.line)"
100000 loops, best of 3: 2.88 usec per loop
编辑:随着需求的轻微变化,我尝试了optionC
的findall
和稍微不同的optionA
:
import re
regex = re.compile(r'(\d+):(\d+)')
def optionA(line):
_id, info = line.split("@")
data = {}
for g_info in info.split(";"):
k, v = g_info.split(":")
data[k] = v
return data
def optionAA(line):
data = {}
for g_info in line[2:].split(";"):
k, v = g_info.split(":")
data[k] = v
return data
def optionB(line):
_id, info = line.split("@")
return dict(map(lambda i: i.split(":"), info.split(";")))
def optionC(line):
return dict(regex.findall(line))
line = 'A@1:100;2:240;3:250;4:260;5:100;6:100;7:100;8:100;9:100;10:100'
时间:
C:\>py -m timeit -s "import x" "x.optionA(x.line)"
100000 loops, best of 3: 8.35 usec per loop
C:\>py -m timeit -s "import x" "x.optionAA(x.line)"
100000 loops, best of 3: 8.17 usec per loop
C:\>py -m timeit -s "import x" "x.optionB(x.line)"
100000 loops, best of 3: 12.3 usec per loop
C:\>py -m timeit -s "import x" "x.optionC(x.line)"
100000 loops, best of 3: 12.8 usec per loop
因此,看起来修改后的
选项aa
在这一行中获胜。希望这能说明测量算法的重要性。我很惊讶findall
的速度较慢。下面是一个使用已编译的regexp匹配您的模式的简单示例
import re
s = "A@1:100;2:240"
compiledre = re.compile("A@(\d+):(\d+);(\d+):(\d+)$")
res = compiledre.search(s)
if res:
print dict([(res.group(1),res.group(2)),(res.group(3),res.group(4))])
输出为:
{'1': '100', '2': '240'}
你对正则表达式有多好?如果文件太大,读取它已经是一个问题,那么是什么让你认为把所有数据都放在内存字典中会更好呢?@poke,请再仔细阅读一遍。我将创建一个临时字典发送到另一个方法。这本字典将是一个方法的输入。为什么不对两个版本都使用
timeit
?@poke,OP正在逐行处理。听起来临时字典一次只存在一行。OP没有存储内存中所有行的所有字典。我喜欢你的替代方案。我只需要看看它在两个以上的组中的行为,我的意思是,如果line=A@1:100;2:240;3:122;...'
@RicardoSilveira您的问题中必须指定更长输入的可能性。@RicardoSilveira,dict(re.findall(r'(\d+):(\d+),line))
将是查找所有对的快速方法,但您确实应该根据该要求更新您的问题。抱歉,我刚刚更新了它。这是因为当我写选项A和B时,我想我已经清楚地表明它可能更长。@RicardoSilveira,我用更长的一行进行了一些计时。请参见编辑。
{'1': '100', '2': '240'}