我有Array{Tuple{A, B}}
,我想将其解压缩/转置为Tuple{Array{A}, Array{B}}
。
typealias MyIndexType Tuple{Bool, Int}
function test(x::MyIndexType)
# prepare for test data set.
myArray = Array{Tuple{MyIndexType, Float64}}(0)
push!(myArray, (x,1))
push!(myArray, (x,1))
push!(myArray, (x,1))
# transform
a, b = (zip(myArray...)...)
[a...]
end
test((true, 1))
>>>
3-element Array{Tuple{Bool,Int64},1}:
(true,1)
(true,1)
(true,1)
但是,使用@code_warntype
时,JIT无法提前推断出a
,b
的类型。
Variables:
x::Tuple{Bool,Int64}
myArray::Array{Tuple{Tuple{Bool,Int64},Float64},1}
a::ANY
b::ANY
#s41::Int64
Body:
begin # In[47], line 6:
myArray = (top(ccall))(:jl_alloc_array_1d,(top(apply_type))(Base.Array,Tuple{Tuple{Bool,Int64},Float64},1)::Type{Array{Tuple{Tuple{Bool,Int64},Float64},1}},(top(svec))(Base.Any,Base.Int)::SimpleVector,Array{Tuple{Tuple{Bool,Int64},Float64},1},0,0,0)::Array{Tuple{Tuple{Bool,Int64},Float64},1} # In[47], line 7:
(Main.push!)(myArray::Array{Tuple{Tuple{Bool,Int64},Float64},1},(top(tuple))(x::Tuple{Bool,Int64},1)::Tuple{Tuple{Bool,Int64},Int64})::Array{Tuple{Tuple{Bool,Int64},Float64},1} # In[47], line 8:
(Main.push!)(myArray::Array{Tuple{Tuple{Bool,Int64},Float64},1},(top(tuple))(x::Tuple{Bool,Int64},1)::Tuple{Tuple{Bool,Int64},Int64})::Array{Tuple{Tuple{Bool,Int64},Float64},1} # In[47], line 9:
(Main.push!)(myArray::Array{Tuple{Tuple{Bool,Int64},Float64},1},(top(tuple))(x::Tuple{Bool,Int64},1)::Tuple{Tuple{Bool,Int64},Int64})::Array{Tuple{Tuple{Bool,Int64},Float64},1} # In[47], line 10:
GenSym(0) = (top(_apply))((top(getfield))(Main,:call)::F,top(tuple),(top(_apply))((top(getfield))(Main,:call)::F,Main.zip,myArray::Array{Tuple{Tuple{Bool,Int64},Float64},1})::UNION{BASE.ZIP2{TUPLE{TUPLE{BOOL,INT64},FLOAT64},TUPLE{TUPLE{BOOL,INT64},FLOAT64}},TUPLE{TUPLE{BOOL,INT64},FLOAT64},ZIP{I,Z<:BASE.ABSTRACTZIPITERATOR}})::TUPLE
#s41 = 1
GenSym(4) = (Base.getfield)(GenSym(0),1)::ANY
GenSym(5) = (Base.box)(Base.Int,(Base.add_int)(1,1)::ANY)::Int64
a = GenSym(4)
#s41 = GenSym(5)
GenSym(6) = (Base.getfield)(GenSym(0),2)::ANY
GenSym(7) = (Base.box)(Base.Int,(Base.add_int)(2,1)::ANY)::Int64
b = GenSym(6)
#s41 = GenSym(7) # In[47], line 11:
return (top(_apply))((top(getfield))(Main,:call)::F,top(vect),a)::ANY
end::ANY
有没有办法让zip知道结果类型?
实际上有两个问题。
它认为a
属于a::TUPLE{UNION{FLOAT64,INT64},UNION{FLOAT64,INT64}}
类型,但实际上属于a::TUPLE{FLOAT64,FLOAT64}
function test{T}(x::T)
A = Tuple{T, Int}[]
for i in 1:3
push!(A, (x, 1))
end
d = zip(A[1], A[2])
a, b = d
a
end
@code_warntype test(3.0)
Variables:
x::Float64
A::Array{Tuple{Float64,Int64},1}
d::Base.Zip2{Tuple{Float64,Int64},Tuple{Float64,Int64}}
a::TUPLE{UNION{FLOAT64,INT64},UNION{FLOAT64,INT64}}
b::TUPLE{UNION{FLOAT64,INT64},UNION{FLOAT64,INT64}}
#s40::Tuple{Int64,Int64}
#s41::Int64
i::Int64
对于zip
超过2个参数,请注意d有一个嵌套的zip2
类型,我觉得这可能会给类型推断带来负担。
function test{T}(x::T)
A = Tuple{T, Int}[]
for i in 1:3
push!(A, (x, 1))
end
d = zip(A[1], A[2], A[3])
a, b = d
a
end
@code_warntype test(3.0)
Variables:
x::Float64
A::Array{Tuple{Float64,Int64},1}
d::Zip{Tuple{Float64,Int64},Base.Zip2{Tuple{Float64,Int64},Tuple{Float64,Int64}}}
a::TUPLE{UNION{FLOAT64,INT64},UNION{FLOAT64,INT64},UNION{FLOAT64,INT64}}
b::TUPLE{UNION{FLOAT64,INT64},UNION{FLOAT64,INT64},UNION{FLOAT64,INT64}}
#s40::Tuple{Int64,Tuple{Int64,Int64}}
#s41::Int64
i::Int64
##c#7879::Tuple{Tuple{Float64,Int64}}
编译以下示例的a,b = zip(A ...)需要10秒以上,速度似乎与A的长度有关。(Julia 0.4)
const A = Tuple{Int, Int}[]
for i = 1:200
push!(A, (1, 1))
end
a, b = zip(A...)
a
我在这里打开了一个错误报告canvas
答案 0 :(得分:1)
我认为@code_warntype
报告如果最终确定正确的类型,则无法推断它是不是一个问题。
我仍然想知道这是否是由于您的类型的复杂性。但它不是,如下面的代码所示(具有更简单的类型)。
请注意,您还可以简化zip
表达式;而且您可能不需要将a
转换为数组。
代码:
function test{T}(x::T)
A = Tuple{T, Int}[]
for i in 1:3
push!(A, (x, 1))
end
a, b = zip(A...)
a, b
end
julia> test(3) # now returns a and b
((3,3,3),(2,2,2))
julia> @code_warntype test(3)
Variables:
x::Int64
A::Array{Tuple{Int64,Int64},1}
a::ANY
b::ANY
#s40::ANY
#s41::Int64
i::Int64