我正在尝试在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缓冲区?
答案 0 :(得分:2)
您遇到问题的原因是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
实际上,您可以使用invoke
类型和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
类型填充数组(这不是推荐的方法,但会向您显示差异):
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
最后,正如所讨论的here,要记住的一个问题是,理解将为创建的数组的每个条目调用一个函数,但是如果使用宏,它将只被调用一次。以下是链接中详细解释的简短示例:
employer