-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature request: std::partition #81
Comments
This is already possible with
Benchmarksusing Chairmarks, Plots
function partition!(v::AbstractVector; by)
i, j = firstindex(v), lastindex(v)
@inbounds while true
while !by(v[i]); i += 1; end;
while by(v[j]); j -= 1; end;
i >= j && break
v[i], v[j] = v[j], v[i]
i += 1; j -= 1
end
v # maybe return j?
end
@time for n in 1:100
x = rand(1:10, n);
# @assert sort!(copy(x), by=iseven) == partition!(copy(x), by=iseven) # (sort! is stable, partition! is not)
@assert iseven.(sort!(copy(x), by=iseven)) == iseven.(partition!(copy(x), by=iseven))
end
f(n) = (@b n sort!(rand(1:10, _), by=iseven) seconds=.02).time
g(n) = (@b n partition!(rand(1:10, _), by=iseven) seconds=.02).time
x = unique(round.(Int, 2 .* 1.1 .^ (1:150)));
@time y = [f(n) for n in x];
@time z = [g(n) for n in x];
plot(x, 1e9y ./ x, label="sort!", xaxis=:log, ylabel="time per element (ns)", xlabel="length", legend=:topleft, ylims=(0, 35), xticks=10)
plot!(x, 1e9z ./ x, label="partition!", xaxis=:log) Do either of you have large inputs and care about a 4x performance loss? or want the index where the low values transition to high values? ( Maybe I'll make If we do this we could either use partition!(by, x) or sort!(x; rev, by, ..., alg=Partition) |
I don't especially feel the need for this functionality at the moment, but if we do implement it, it should probably be one that returns the cutoff/transition locations (or equivalently the a tuple of views/slices). |
Yeah, for now I've basically been using this: function partition!(f, x)
sort!(x; by=!f)
findfirst(!f, x)
end I guess it would make sense to bikeshed the name with |
lol, yeah. Stability characteristics are another thing. You can get no stability, one-sided stability, or two-sided stability (though I can't think of any way to get two-sided stability in place and in linear time). We use all three stability characteristics in various places within Base.Sort. |
Nice blog post on implementing |
Some design questions and proposed answers to those questions Return value
Order
Input
Proposal export partition, partition!
public Stable, Unstable, ReverseStable
abstract type Stability end
struct Stable <: Stability end
struct Unstable <: Stability end
struct ReverseStable <: Stability end
partition!(by, v; stability=Unstable; false_stability=stability; true_stability=stability) -> NTuple{2, SubArray}
partition!(by, dest, src; stability=Stable; false_stability=stability; true_stability=stability) -> NTuple{2, SubArray}
partition(by, v; kws...) = partition!(by, similar(v), v; kws...)::NTuple{2, SubArray} Of which I'm certainly open to feedback and other ideas! |
Following this slack thread, it would be nice to have an implementation of std::partition.
The text was updated successfully, but these errors were encountered: