Creating ranges from findall

Do you know of a way to turn the results of findall into Vector{UnitRange{Int64}}?

searching = DataFrame(A = 1:5:1000)

searching_specific = searching[:,:A]

findall(x -> isodd(x), searching_specific)

The results look like: 1, 3, 5, 7, 9, 11 etc.

I want to be able to create ranges from this like

[1:2]
[3:4]
[5:6]

Creating a range using a value and -1 from the next value point.

I’m not at my computer, so your mwe confuses me a bit. What is the purpose of the DataFrame here? What does searching_specific contain? Can you create it without going through the DataFrame, for clarity?

A = 1:5:1000
F = findall(isodd, A)
R = [i:j-1 for (i, j) in zip(F[1:end-1], F[2:end])]

There’s probably a better way, but this does what you want.

inds = findall(isodd, searching_specific)
ranges = @views (:).(inds[1:end-1], inds[2:end] .- 1)

This allocates, but it seems not to be a problem since you are using findall. If you want an allocation-free alternative, you may create a new iterable type like this:

struct FindRanges{F, T}
	f::F
	t::T
end
function Base.iterate(x::FindRanges, i1 = findfirst(x.f, x.t))
	i2 = findnext(x.f, x.t, nextind(x.t, i1))
	if i2 === nothing
		nothing
	else
		i1 : prevind(x.t, i2), i2
	end
end

ranges2 = FindRanges(isodd, searching_specific)

ranges2 is a iterable that yields the same as ranges, but without allocations.

1 Like

Thank you for your replies.

@DNF Maybe it doesn’t need to be in a DataFrame. I have a long file of outputs from the same DifferentialEquation that I want to plot individually. I harvest a different species from the same food web, and save the outputs one after the other. searching_specific is when the time step is 0.0 (different from the MWE). I want the indices of where the 0.0 are, and create ranges from them so I can create plots. I keep it as DataFrame because I find :Symbol practical for plotting.

image

I don’t know if plotting this way will work, but now I can try. Thank you