Tcl 快速字符串替换
在构建了一个可能非常大的字符串之后,我将对其中的单个字符(或者字节,如果必要的话)进行大量更改,以转换为另一个字符 实际上,我的脚本正在构建一个纵横字谜,所以字符串不会很长,但我的问题是一般性的: 我怎样才能利用我没有改变字符串(或任何更好的数据类型)长度的事实来加快速度呢 我想我要寻找的部分是一种发送指针或字符串引用的方法,或者在Tcl的情况下发送变量名 我的另一个问题是C代码内部发生了什么 这个调用会将整个字符串复制零次、一次甚至两次吗Tcl 快速字符串替换,tcl,Tcl,在构建了一个可能非常大的字符串之后,我将对其中的单个字符(或者字节,如果必要的话)进行大量更改,以转换为另一个字符 实际上,我的脚本正在构建一个纵横字谜,所以字符串不会很长,但我的问题是一般性的: 我怎样才能利用我没有改变字符串(或任何更好的数据类型)长度的事实来加快速度呢 我想我要寻找的部分是一种发送指针或字符串引用的方法,或者在Tcl的情况下发送变量名 我的另一个问题是C代码内部发生了什么 这个调用会将整个字符串复制零次、一次甚至两次吗 set index [expr {$row * $wi
set index [expr {$row * $width + $col}]
set puzzle [string replace $puzzle $index $index "E"]
只要满足两个条件,
string replace
操作将执行就地更改:
字符串替换
完成之前(设置需要结果才能工作),字符串的旧版本仍然处于拼图
中。为了解决这个问题,我们做了一件稍微奇怪的事情:
set puzzle [string replace $puzzle[set puzzle {}] $index $index "E"]
是的,这很奇怪,但它工作得很好,因为与已知的空字符串连接是一种显式优化的情况,假设您处理的是未跟踪的变量。(它将与跟踪变量一起工作,但双写是可观察的,跟踪可能会做一些棘手的事情,因此您将失去优化机会。)
如果您正在进行大量的更改,有时会改变内容的长度,那么切换到使用列表和lset
会更有效。列表上的等效操作都使用相同的通用引用和就地语义,但使用列表元素而不是字符
拆卸 我所说的优化是在
strcat
操作码中,并且strreplace
知道在可能的情况下执行,但您看不到字节码级别的信息;几乎所有的行动都知道这一点
% tcl::unsupported::disassemble lambda {{puzzle index} {
set puzzle [string replace $puzzle[set puzzle {}] $index $index "E"]
}}
ByteCode 0x0x7fbff6021c10, refCt 1, epoch 17, interp 0x0x7fbff481e010 (epoch 17)
Source "\n set puzzle [string replace $puzzle[set puzzle {}]..."
Cmds 3, src 74, inst 18, litObjs 2, aux 0, stkDepth 4, code/src 0.00
Proc 0x0x7fbff601cc90, refCt 1, args 2, compiled locals 2
slot 0, scalar, arg, "puzzle"
slot 1, scalar, arg, "index"
Commands 3:
1: pc 0-16, src 5-72 2: pc 0-14, src 17-71
3: pc 2-5, src 40-52
Command 1: "set puzzle [string replace $puzzle[set puzzle {}] $inde..."
Command 2: "string replace $puzzle[set puzzle {}] $index $index \"E..."
(0) loadScalar1 %v0 # var "puzzle"
Command 3: "set puzzle {}..."
(2) push1 0 # ""
(4) storeScalar1 %v0 # var "puzzle"
(6) strcat 2
(8) loadScalar1 %v1 # var "index"
(10) loadScalar1 %v1 # var "index"
(12) push1 1 # "E"
(14) strreplace
(15) storeScalar1 %v0 # var "puzzle"
(17) done
如果要对任何值进行大量修改,请使用过程、lambda或方法。局部变量比全局变量快得多。所以将变量设置为空字符串,删除对它的引用?是否有任何就地指挥的计划,或者在某些地方,这会打破Tcl的主张?无论如何,谢谢你提供的信息性答案,我喜欢这种语言。对包含字符串的变量进行操作的就地命令?没有具体的计划。也没有人反对;最难的一点是选择一个名称。显然,名称应该反映您作为程序员或脚本编写者所寻找的内容。Tcl在某些命令(或所有命令)中进行了内部优化,以避免内存重新分配,这一事实肯定不会污染文档。我(认真地)建议名称
poke
和peek
。当然,在fconfigure
命令的控制下,这是Tcl的诸多优势之一。打开一个流到内存中,这在语言中是一种新的方式吗?