Chris Rackauckas
Chris Rackauckas

Reputation: 19162

Loop over iterator with changing size and values

This is best explained by example. I would like to do something like:

tstops = [20;40]
for i in eachindex(tstops)
  if tstops[i] == 20
    push!(tstops,70)
  end
  if tstops[i] == 40
    push!(tstops,60)
  end
  if tstops[i] == 70
     tstops[end] = 100
  end
  @show tstops[i]
end

but actually have it show 20, 40, 60, 70, 100 (in that order). The problem with this setup is that eachindex(tstops) is a Base.OneTo{2} and so it only prints 20 and then 40, without dynamically changing. If I instead use the iterator directly:

tstops = [20;40]
for t in tstops
  if t == 20
    push!(tstops,70)
  end
  if t == 40
    push!(tstops,60)
  end
  if t == 70
     tstops[end] = 100
  end
  @show tstops
  @show t
end

This outputs:

tstops = [20,40,70]
t = 20
tstops = [20,40,70,60]
t = 40
tstops = [20,40,70,100]
t = 70
tstops = [20,40,70,100]
t = 100

So I would need a fast way to keep this sorted for this to work. However, even if it goes in sorted, the mutation at the end doesn't make it hit both 70 and 100, just 70:

tstops = [20;40]
for t in tstops
  if t == 20
    push!(tstops,60)
  end
  if t == 40
    push!(tstops,70)
  end
  if t == 70
     tstops[end] = 100
  end
  @show tstops
  @show t
end

Note that the implementation should try to get as good performance as possible too. Is there a good data structure to handle this, both the sorting and the "mutating the current point"?


Edit

Let me try to summarize it in one line: I want to be able to loop through t in tstops and hit every value of tstops in order, but (the hard part) I want to be able to dynamically change tstops.

Upvotes: 2

Views: 154

Answers (1)

Dan Getz
Dan Getz

Reputation: 18227

The exact behavior desired is not clear to me, but perhaps this will do:

using Base.Collections
tstops = [20,40]
heapify!(tstops)
while !isempty(tstops)
  t = heappop!(tstops)
  if t == 20
    heappush!(tstops,70)
  end
  if t == 40
    heappush!(tstops,60)
  end
  if t == 70
    heappush!(tstops,100)
  end
  @show tstops
  @show t
end

Which results in:

tstops = [40,70]
t = 20
tstops = [60,70]
t = 40
tstops = [70]
t = 60
tstops = [100]
t = 70
tstops = Int64[]
t = 100

Upvotes: 3

Related Questions