在SQLite和/或Tcl中,有没有一种快速的方法可以将一个字符串分割成等长的段?
我的目标是在内存中获取一个字符串,并将拆分写入表中的行。有时字符串通过通道传递,有时它是从SQLite表中已经保存的片段连接起来的。
我一直在使用substr
的CTE,我能得到的最好的结果是大约1.6秒,一个大约1 MB的字符串变成4216个/行。
最简单的拆分尝试示例是
select
sg.value, substr(:textContent, sg.value, 250)
from
generate_series(1, :tcLen, 250) sg
;
字符串
使用group_concat
组合表中的4216个片段只需要0.129秒,并且每行都包含一个substr
来选择每行的全部或部分字符串。
感谢您提供的任何指导。
编辑:
我现在看到这个answer在tcllib
中提到了:textutil::spit::splitn
。将给予尝试;应该想到在那里查找,但假设SQL会更快。
使用下面的文本工具并插入循环中,将1.6秒减少到大约0.26秒。
foreach row [::textutil::split::splitn $textContent $bufferRowMaxLength] {
set charLength [expr {min([string length $row], $bufferRowMaxLength)}]
db eval {
insert into mem.pt_buffers values ( ... );
insert into mem.pt_pointer values ( ... );
}
}
型
1条答案
按热度按时间jgzswidk1#
textutil::split::splitn
非常快,尽管它只是该解决方案的明显Tcl脚本,比我用c所能做的最好的慢2倍。不应该太令人惊讶,Tcl真的很擅长处理字符串。我尝试的一个替代方法(基于Donal多年前分享的一个技巧)是用
regexp
分块:字符串
但这是令人惊讶的慢。
以下是我的所有结果:
的数据
regexp
的实现比其他实现慢得多,这表明它的实现还有一些改进的空间,一些不明显的低效率。但对我来说,只要你有用块内容组装Tcl列表的约束,那么
::textutil::split::splitn
(或Tcl的等效几行)可能是正确的方法。在我的书中,c实现增加的复杂性并不足以证明自己,而且几乎可以肯定的是,对块本身所做的任何工作都会完全抵消这些好处。请注意,c实现在这里并不等同于Tcl或regexp实现--它们分割成$bufferMaxRowLength字节的块,而不是字符。(而不是bytearray,在这种情况下,实现是等效的),则c实现产生的块是表示CESU-8编码中的字符串的字节块(类似UTF-8,但将空字节编码为0xC 0 0x 80,并对BMP之外的字符使用代理对)。这些字节块边界可能会分割单个字符的编码,因此块本身不会是字符串的有效编码。它们的目的是作为计算此结果所需的最小工作量的替代,任何按字符拆分的实现都必须完成它们的工作,并考虑字符边界,因此它们作为工作的下限估计是有效的。