实际上,这是一个简单的问题:您有 10 亿 (1e+9) 个无符号 32 位整数作为十进制 ASCII 字符串存储在 TSV(制表符分隔值)文件中。int()与处理同一数据集的其他工具相比,转换速度非常慢。为什么?更重要的是:如何让它更快?
因此问题是:在Python中将字符串转换为整数的最快方法是什么?
我真正想到的是一些半隐藏的 Python 功能,可以(滥用)用于此目的,与 Guidoarray.array在他的“优化轶事”中的使用不同。
示例数据(制表符扩展为空格)
38262904 "pfv" 2002-11-15T00:37:20+00:00
12311231 "tnealzref" 2008-01-21T20:46:51+00:00
26783384 "hayb" 2004-02-14T20:43:45+00:00
812874 "qevzasdfvnp" 2005-01-11T00:29:46+00:00
22312733 "bdumtddyasb" 2009-01-17T20:41:04+00:00
Run Code Online (Sandbox Code Playgroud)
读取数据所花费的时间在这里无关紧要,处理数据才是瓶颈。
微基准测试
以下所有语言都是解释性语言。主机运行 64 位 Linux。
Python 2.6.2 和 IPython 0.9.1,每秒约 214k 次转换 (100%):
In [1]: strings = map(str, range(int(1e7)))
In [2]: %timeit map(int, strings);
10 loops, best of 3: 4.68 s per loop
Run Code Online (Sandbox Code Playgroud)
REBOL 3.0 版本 2.100.76.4.2,~231kcps (108%):
>> strings: array …Run Code Online (Sandbox Code Playgroud) 此代码返回-1R3和+1R2.我想知道我做错了什么.
f: func [] [
also return 1
return -1
]
f
Run Code Online (Sandbox Code Playgroud) 我还没弄清楚如何以更干净的方式分割字符串.
ref: copy/part (find line "#") -15
rest2: copy/part (skip (find line "#") 1) 450
Run Code Online (Sandbox Code Playgroud)
-15用于开始,450用于结束.
这不好,因为我投入了价值.
什么是正确的解决方案?
我想比较字符,看看它们是否匹配.我无法弄清楚为什么它不起作用.我期待true输出,但我变得虚假.
character: "a"
word: "aardvark"
(first word) = character ; expecting true, getting false
Run Code Online (Sandbox Code Playgroud) 我的第一个假设是对象和上下文是同义词.所以我创建了一个对象o和一个上下文c.探测它们会报告相同的代码构造,并且类型也是相同的(都是类型对象!):
>> o: make object! [a: 1 b: 2]
>> c: context [a: 1 b: 2]
>> probe o
make object! [
a: 1
b: 2
]
>> probe c
make object! [
a: 1
b: 2
]
>> type? o
== object!
>> type? c
== object!
Run Code Online (Sandbox Code Playgroud)
...但是在测试平等时,你得到:
>> equal? o c
== false
Run Code Online (Sandbox Code Playgroud)
所以很明显它们不是同义词.如果他们探测完全相同,为什么不呢?
使用R3,我需要从使用cookie来处理此问题的网站获取页面的本地化版本.在REBOL 2.x中,我可以这样做:
page: http://www.rci.com/resort-directory/resortDetails?resortCode=0450
read/custom page [header [Cookie: "USER_LOCALE=fr_FR"]]
Run Code Online (Sandbox Code Playgroud)
基于R3的粗略文档,我应该能够做到这样的事情:
result: write page [GET [Cookie: "USER_LOCALE"] {fr_FR}]
Run Code Online (Sandbox Code Playgroud)
有人有主意吗?R2方法运行良好,但由于R2不能处理许多外语所需的UTF-8,因此对我来说没什么用处.
**更新**
在我的例子中R2的解决方案(重申)是:
在cookie中组装所需的参数:
cookie-str: "USER_LOCALE=fr_FR; USER_COUNTRY=US"
Run Code Online (Sandbox Code Playgroud)然后将cookie注入标题
page-code: read/custom page reduce compose/deep ['header [Cookie: (cookie-str)]]
Run Code Online (Sandbox Code Playgroud)我在R3中的示例的解决方案是:
page-code: to-string write page reduce compose/deep ['GET [Cookie: (cookie-str)]]
Run Code Online (Sandbox Code Playgroud) 我有一个0和1的线性列表,我需要匹配多个简单模式并找到第一个出现.例如,我可能需要寻找0001101101,01010100100,或10100100010长度800万的名单之内.我只需要找到第一个出现的,然后返回它发生的索引.但是,对大型列表进行循环和访问可能很昂贵,而且我宁愿不要这么做太多次.
有没有比做更快的方法
foreach (patterns) {
for (i=0; i < listLength; i++)
for(t=0; t < patternlength; t++)
if( list[i+t] != pattern[t] ) {
break;
}
if( t == patternlength - 1 ) {
return i; // pattern found!
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
编辑: BTW,我已经按照上面的伪代码实现了这个程序,性能还可以,但没什么了不起的.我估计我在处理器的单个核心上每秒处理大约600万比特.我正在使用它进行图像处理,它必须经过几千万像素的图像,所以每一点都有帮助.
编辑:如果不清楚,我正在使用一个数组,所以只有两种可能:ONE和ZERO.它是在C++中.
编辑:感谢BM和KMP算法的指针.我注意到,在BM的维基百科页面上,它说
该算法预处理正在搜索的目标字符串(键),但不预处理正在搜索的字符串(与预处理要搜索的字符串的某些算法不同,然后可以通过重复搜索来分摊预处理的费用).
这看起来很有趣,但它没有给出任何这种算法的例子.这样的事情也有帮助吗?
在Rebol 2中:
>> foo: make object! [a: 10 b: 20]
>> foo/a
== 10
>> foo/b
== 20
>> first foo
== [self a b]
>> second foo
== [make object! [
a: 10
b: 20
] 10 20]
>> third foo
== [a: 10 b: 20]
>> fourth foo
** Script Error: fourth expected series argument of type:
series date port tuple event
** Near: fourth foo
Run Code Online (Sandbox Code Playgroud)
所以你可以选择它,好像它是值为1,2,3的块.但是在Rebol 3中进行位置选择:
>> first foo
** Script error: cannot use pick on …Run Code Online (Sandbox Code Playgroud)