From 940177a44eb1b9cb421594254bfadca0ef12dae4 Mon Sep 17 00:00:00 2001 From: David Gustavsson Date: Sat, 28 Nov 2020 20:05:50 +0100 Subject: [PATCH 1/2] Change tab indentation to space indentation --- src/IterTools.jl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/IterTools.jl b/src/IterTools.jl index f8f11d2..71fdfc1 100644 --- a/src/IterTools.jl +++ b/src/IterTools.jl @@ -590,14 +590,14 @@ iterate(it::StaticSizeBinomial{0}, state=false) = state ? nothing : ((), true) pop(t::NTuple) = reverse(tail(reverse(t))), t[end] function advance(it::StaticSizeBinomial{K}, idx) where {K} - xs = it.xs - lidx, i = pop(idx) + xs = it.xs + lidx, i = pop(idx) i += 1 - if i > length(xs) - K + length(idx) - lidx = advance(it, lidx) - i = lidx[end] + 1 - end - return (lidx..., i) + if i > length(xs) - K + length(idx) + lidx = advance(it, lidx) + i = lidx[end] + 1 + end + return (lidx..., i) end advance(it::StaticSizeBinomial, idx::NTuple{1}) = (idx[end]+1,) From 6848eedf7e7599d872c4f922fb4bb94205c2e8bf Mon Sep 17 00:00:00 2001 From: David Gustavsson Date: Sat, 28 Nov 2020 21:10:13 +0100 Subject: [PATCH 2/2] Add alternate --- src/IterTools.jl | 67 +++++++++++++++++++++++++++++++++++++++++++++++- test/runtests.jl | 18 +++++++++++++ 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/src/IterTools.jl b/src/IterTools.jl index 71fdfc1..ac477b2 100644 --- a/src/IterTools.jl +++ b/src/IterTools.jl @@ -30,7 +30,9 @@ export takewhile, properties, propertyvalues, - fieldvalues + fieldvalues, + alternate + function has_length(it) it_size = IteratorSize(it) @@ -1031,4 +1033,67 @@ function iterate(fs::FieldValues, state=1) return (getfield(fs.x, state), state + 1) end +# Alternate + +struct Alternate{Is<:Tuple} + xs::Is +end +""" + alternate(xs...) +Alternates through each of the given iterators in order, shuffling their values +until one of them runs out. + +```jldoctest +julia> collect(alternate(1:5,10:-1:1)) + 1 + 10 + 2 + 9 + 3 + 8 + 4 + 7 + 5 + 6 +``` +""" +alternate(xs...) = length(xs) == 1 ? xs[1] : Alternate(xs) +function Base.iterate(it::Alternate, state=1) + if state == 1 + state=[Array{Any}(nothing,length(it.xs)),1] + end + if isnothing(state[1][state[2]]) + itreturn = iterate(it.xs[state[2]]) + else + itreturn = iterate(it.xs[state[2]],state[1][state[2]]) + end + isnothing(itreturn) && return nothing + state[1][state[2]] = itreturn[2] + state[2] = (state[2] % length(it.xs)) + 1 + return (itreturn[1],state) +end +function IteratorEltype(::Type{Alternate{Is}}) where Is + iteratoreltypes = IteratorEltype.(fieldtypes(Is)) + any(iteratoreltypes .== Ref(EltypeUnknown())) && return EltypeUnknown() + return HasEltype() +end +eltype(::Type{Alternate{Is}}) where Is = Union{eltype.(fieldtypes(Is))...} +function IteratorSize(::Type{Alternate{Is}}) where Is + iteratorsizes = IteratorSize.(fieldtypes(Is)) + any(iteratorsizes .== Ref(SizeUnknown())) && return SizeUnknown() + all(iteratorsizes .== Ref(IsInfinite())) && return IsInfinite() + return HasLength() # Never returns HasShape +end +function length(i::Alternate) + m = Int64(minimum(IteratorSize(x) isa IsInfinite ? Inf : length(x) for x in i.xs)) + l = length(i.xs)*m + for x in i.xs + if IteratorSize(x) isa IsInfinite || length(x) > m + l = l+1 + else + return l + end + end +end + end # module IterTools diff --git a/test/runtests.jl b/test/runtests.jl index 2fa7de9..c91d786 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -524,6 +524,24 @@ include("testing_macros.jl") @test collect(fv3) == Any[] end + @testset "alternate" begin + intlist1 = 1:5 + intlist2 = 2:4:14 + inflist = countfrom(1) + unklist = takewhile(x -> x ≤ 10, countfrom(1)) + shapedlist = [1 2 3;2 4 6] + str = "String" + @test eltype(alternate(intlist1,intlist2)) == Int64 + @test eltype(alternate(intlist1,str)) == Union{Int64,Char} + @test length(alternate(intlist1,intlist2)) == 9 + @test length(alternate(intlist2,intlist1)) == 8 + @test IteratorSize(alternate(inflist,inflist)) isa IsInfinite + @test IteratorSize(alternate(intlist1,unklist)) isa SizeUnknown + @test IteratorSize(alternate(shapedlist,shapedlist)) isa HasLength + @test alternate(intlist1) == intlist1 + @test collect(alternate(intlist1,intlist2,inflist)) == [1,2,1,2,6,2,3,10,3,4,14,4,5] + end + @testset "traits overriding defaults" begin iters = [ firstrest(1:10),