diff --git a/base/iterators.jl b/base/iterators.jl index 6ad54b5cd00cf..a7d550bf7a625 100644 --- a/base/iterators.jl +++ b/base/iterators.jl @@ -200,9 +200,9 @@ end For a set of iterable objects, returns an iterable of tuples, where the `i`th tuple contains the `i`th component of each input iterable. -Note that [`zip`](@ref) is its own inverse: `collect(zip(zip(a...)...)) == collect(a)`. +Note that the inverse of [`zip`](@ref) is [`unzip`](@ref). -```jldoctest +"""jldoctest julia> a = 1:5 1:5 @@ -222,7 +222,8 @@ julia> length(c) julia> first(c) (1, "e") -``` +""" + """ zip(a, b, c...) = Zip(a, zip(b, c...)) length(z::Zip) = _min_length(z.a, z.z, iteratorsize(z.a), iteratorsize(z.z)) @@ -240,6 +241,34 @@ end iteratorsize{I1,I2}(::Type{Zip{I1,I2}}) = zip_iteratorsize(iteratorsize(I1),iteratorsize(I2)) iteratoreltype{I1,I2}(::Type{Zip{I1,I2}}) = and_iteratoreltype(iteratoreltype(I1),iteratoreltype(I2)) +# unzip +""" + +For iterable objects of the same length, returns iterable sets, where the ith set contains +the ith component of each input iterable object. + +Note that the inverse of [`unzip`](@ref) is [`zip`](@ref). + +```jldoctest +julia> z = [[1,"a",:meow], [2,"b",:woof], [3,"c",:doh!]] +3-element Array{Array{Any,1},1}: +Any[1, "a", :meow] +Any[2, "b", :woof] +Any[3, "c", :doh!] + +julia> unzip(z) +Base.Iterators.Zip2{UnitRange{Int64},Array{Int64,1}}(1:3, [1, 2, 3]) +Base.Iterators.Zip2{UnitRange{Int64},Array{String,1}}(1:3, String["a", "b", "c"]) +Base.Iterators.Zip2{UnitRange{Int64},Array{Symbol,1}}(1:3, [:meow, :woof, :doh!]) +``` +""" +unzip(iter::AbstractZipIterator) = _unzip(iter) +# This avoids exporting the method that isn't for AbstractZipIterators +_unzip(iter::Zip1) = (iter.a,) +_unzip(iter::Zip2) = (iter.a, iter.b) +_unzip(iter::Zip) = (iter.a, _unzip(iter.z)...) +_unzip(iter) = (iter,) + # filter struct Filter{F,I} diff --git a/test/iterators.jl b/test/iterators.jl index d3e8baf65dd1d..a724aa86eb016 100644 --- a/test/iterators.jl +++ b/test/iterators.jl @@ -22,6 +22,22 @@ let z = zip(1:2, 3:4, 5:6) @test eltype(z) == Tuple{Int,Int,Int} end +# unzip +let z = zip(1:2) + @test unzip(z) == (1:2,) + @test eltype(unzip(z)) == UnitRange{Int} +end + +let z = zip(1:2, 3:4) + @test collect(unzip(z)) == [(1,2), (3,4)] + @test eltype(unzip(z)) == UnitRange{Int} +end + +let z = zip(1:2, 3:4, 5:6) + @test collect(unzip(z)) == [(1,2), (3,4), (5,6)] + @test eltype(unzip(z)) == UnitRange{Int} +end + @test eltype(Iterators.filter(isodd, 1:5)) == Int # typed `collect`