我正在尝试在 Julia 中处理长文本字符串(例如书籍长度)的不同方法。具体来说,我正在研究转置密码,并使用 (1) 字符串连接、(2) 数组和 (3) I/O 缓冲区来测试速度和内存使用情况。在最后一种情况下,我需要能够将单个字符“打印”到不同的可索引 I/O 缓冲区。我的第一次(简化的)尝试如下:
text = fill(IOBuffer(), 3)
print(text[1], 'a')
print(text[2], 'b')
print(text[3], 'c')
for i in 1:3
println(String(take!(text[i])))
end
这会产生:
"abc"
""
""
换句话说,第一个索引返回整个字符串 "abc"
而不仅仅是所需的字符 'a'
,其他索引生成空字符串 ""
因为缓冲区在第一个 take!()
函数之后被重置。
我的下一次尝试成功了,但看起来不太复杂:
text = Vector(3)
for i in 1:3
text[i] = IOBuffer()
end
print(text[1], 'a')
print(text[2], 'b')
print(text[3], 'c')
for i in 1:3
println(String(take!(text[i])))
end
这会产生所需的输出:
"a"
"b"
"c"
我仍然不完全确定为什么第一种方法失败而第二种方法有效,但是有人知道设置多个可以使用索引写入的 I/O 缓冲区的更好方法吗?
最佳答案
问题的原因是在 text = fill(IOBuffer(), 3)
中,调用 IOBuffer()
仅评估一次,因此 的所有条目>text
指向同一个对象。您可以通过运行来检查:
julia> all(x->x===text[1], text)
true
或者你可以在运行时看到:
julia> fill(println("AAA"), 3)
AAA
3-element Array{Void,1}:
nothing
nothing
nothing
发现 println
仅被调用一次 - 在将其值传递给 fill
方法之前。
解决这个问题的最简单方法是使用理解:
julia> text = [IOBuffer() for i in 1:3]
3-element Array{Base.AbstractIOBuffer{Array{UInt8,1}},1}:
IOBuffer(data=UInt8[...], readable=true, writable=true, seekable=true, append=false, size=0, maxsize=Inf, ptr=1, mark=-1)
IOBuffer(data=UInt8[...], readable=true, writable=true, seekable=true, append=false, size=0, maxsize=Inf, ptr=1, mark=-1)
IOBuffer(data=UInt8[...], readable=true, writable=true, seekable=true, append=false, size=0, maxsize=Inf, ptr=1, mark=-1)
julia> map(x->x===text[1], text)
3-element Array{Bool,1}:
true
false
false
或 map
(不太干净):
julia> map(i->IOBuffer(), 1:3)
3-element Array{Base.AbstractIOBuffer{Array{UInt8,1}},1}:
IOBuffer(data=UInt8[...], readable=true, writable=true, seekable=true, append=false, size=0, maxsize=Inf, ptr=1, mark=-1)
IOBuffer(data=UInt8[...], readable=true, writable=true, seekable=true, append=false, size=0, maxsize=Inf, ptr=1, mark=-1)
IOBuffer(data=UInt8[...], readable=true, writable=true, seekable=true, append=false, size=0, maxsize=Inf, ptr=1, mark=-1)
julia> map(x->x===text[1], text)
3-element Array{Bool,1}:
true
false
false
实际上,您可以使用 IOBuffer
类型填充数组并调用
它们(这不是推荐的方法,但会向您展示差异):
julia> text = invoke.(fill(IOBuffer, 3), [Tuple{}])
3-element Array{Base.AbstractIOBuffer{Array{UInt8,1}},1}:
IOBuffer(data=UInt8[...], readable=true, writable=true, seekable=true, append=false, size=0, maxsize=Inf, ptr=1, mark=-1)
IOBuffer(data=UInt8[...], readable=true, writable=true, seekable=true, append=false, size=0, maxsize=Inf, ptr=1, mark=-1)
IOBuffer(data=UInt8[...], readable=true, writable=true, seekable=true, append=false, size=0, maxsize=Inf, ptr=1, mark=-1)
julia> map(x->x===text[1], text)
3-element Array{Bool,1}:
true
false
false
最后,需要记住一个要点,正如所讨论的 here ,是理解式将为创建的数组的每个条目调用一个函数,但如果您使用宏,则只会调用一次。这是链接中详细解释的一个简短示例:
julia> rx = [Regex("a") for i in 1:3]
3-element Array{Regex,1}:
r"a"
r"a"
r"a"
julia> map(x->x===rx[1], rx)
3-element Array{Bool,1}:
true
false
false
julia> rx = [r"a" for i in 1:3]
3-element Array{Regex,1}:
r"a"
r"a"
r"a"
julia> map(x->x===rx[1], rx)
3-element Array{Bool,1}:
true
true
true
关于io - 在 Julia 中设置多个 I/O 缓冲区的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49533361/