Skip to content

Commit 0298b33

Browse files
committed
wip: using Pairs (nalimilan) and merge pred/f functions
1 parent b6f1398 commit 0298b33

File tree

4 files changed

+89
-65
lines changed

4 files changed

+89
-65
lines changed

base/array.jl

Lines changed: 64 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1994,48 +1994,64 @@ symdiff(a, b, rest...) = symdiff(a, symdiff(b, rest...))
19941994
# function _replace!(pred::Callable, new::Callable, A::T, n::Int)
19951995

19961996
"""
1997-
replace!(A, old, new, [n::Integer])
1997+
replace!(A, old_new::Pair...; [n::Integer])
19981998
1999-
Replace all occurrences of `old` in collection `A` by `new`.
2000-
If `n` is specified, then replace at most `n` occurrences.
1999+
For each pair `old=>new` in `old_new`, replace all occurrences
2000+
of `old` in collection `A` by `new`.
2001+
If `n` is specified, then replace at most `n` occurrences in total.
20012002
See also [`replace`](@ref).
20022003
20032004
# Examples
20042005
```jldoctest
2005-
julia> replace!([1, 2, 1, 3], 1, 0, 2)
2006+
julia> replace!([1, 2, 1, 3], 1=>0, 2=>4, n=2)
20062007
4-element Array{Int64,1}:
20072008
0
2008-
2
2009-
0
2009+
4
2010+
1
20102011
3
20112012
2012-
julia> replace!(Set([1, 2, 3]), 1, 0)
2013+
julia> replace!(Set([1, 2, 3]), 1=>0)
20132014
Set([0, 2, 3])
20142015
```
20152016
"""
2016-
replace!(A, old, new, n::Integer=typemax(Int)) = replace!(x->x==old, A, new, n)
2017+
function replace!(A, old_new::Pair...; n::Integer=typemax(Int))
2018+
# replace!(x->x==old, A, new, n)
2019+
replace!(A, n=n) do x
2020+
for on in old_new
2021+
first(on) == x && return Nullable(last(on))
2022+
end
2023+
Nullable()
2024+
end
2025+
end
20172026

20182027
"""
2019-
replace!(pred, A, new, [n::Integer])
2020-
replace!(pred, f::Function, A, [n::Integer])
2028+
replace!(pred::Function, A, new; [n::Integer])
20212029
20222030
Replace all occurrences `x` in collection `A` for which `pred(x)` is true
2023-
by `new` or `f(x)`.
2024-
If `n` is specified, then replace at most `n` occurrences.
2031+
by `new`.
20252032
20262033
# Examples
20272034
```jldoctest
2028-
julia> a = [1, 2, 3, 1];
2035+
julia> A = [1, 2, 3, 1];
20292036
2030-
julia> replace!(isodd, a, 0, 2); a
2037+
julia> replace!(isodd, A, 0, n=2); a
20312038
4-element Array{Int64,1}:
20322039
0
20332040
2
20342041
0
20352042
1
2043+
```
2044+
2045+
replace!(prednew::Function, A; [n::Integer])
20362046
2037-
julia> replace!(x->x.first=>3, Dict(1=>2, 3=>4), 1) do kv
2038-
first(kv) < 3
2047+
For each value `x` in `A`, `prednew(x)` is called and must
2048+
return a `Nullable` object. If it is not null, then the wrapped
2049+
value will be used as a replacement for `x`.
2050+
2051+
# Example
2052+
```jldoctest
2053+
julia> replace!(Dict(1=>2, 3=>4)) do kv
2054+
Nullable(first(kv)=>3, first(kv) < 3)
20392055
end
20402056
Dict{Int64,Int64} with 2 entries:
20412057
3 => 4
@@ -2049,77 +2065,84 @@ Dict{Int64,Int64} with 2 entries:
20492065
For example, the following may appear unexpected:
20502066
20512067
```jldoctest
2052-
julia> replace!(x->true, x->2x, Set([3, 6]))
2068+
julia> replace!(x->Nullable(2x), Set([3, 6]))
20532069
Set([12])
20542070
```
20552071
"""
2056-
function replace!(pred::Callable, new::Callable, A, n::Integer=typemax(Int))
2072+
function replace!(prednew::Callable, A; n::Integer=typemax(Int))
20572073
n < 0 && throw(DomainError())
20582074
n == 0 && return A
2059-
_replace!(pred, new, A, clamp(n, 0, typemax(Int)))
2075+
_replace!(prednew, A, clamp(n, 0, typemax(Int)))
20602076
end
20612077

2062-
function _replace!(pred::Callable, new::Callable, A::AbstractArray, n::Int)
2078+
function _replace!(prednew::Callable, A::AbstractArray, n::Int)
20632079
# precondition: n > 0
20642080
count = 0
20652081
@inbounds for i in eachindex(A)
2066-
if pred(A[i])
2067-
A[i] = new(A[i])
2082+
y = prednew(A[i])
2083+
if !isnull(y)
2084+
A[i] = get(y)
20682085
count += 1
20692086
count == n && break
20702087
end
20712088
end
20722089
A
20732090
end
20742091

2075-
replace!(pred::Callable, A, new, n::Integer=typemax(Int)) = replace!(pred, y->new, A, n)
2092+
replace!(pred::Callable, A, new; n::Integer=typemax(Int)) =
2093+
replace!(x->Nullable(new, pred(x)), A, n=n)
20762094

20772095
"""
2078-
replace(A, old, new, [n])
2096+
replace(A, old_new::Pair...; [n::Integer])
20792097
2080-
Return a copy of collection `A` where all occurrences of `old` are
2081-
replaced by `new`.
2082-
If `n` is specified, then replace at most `n` occurrences.
2098+
Return a copy of collection `A` where, for each pair `old=>new` in `old_new`,
2099+
all occurrences of `old` are replaced by `new`.
2100+
If `n` is specified, then replace at most `n` occurrences in total.
20832101
See also [`replace!`](@ref).
20842102
20852103
# Examples
20862104
20872105
```jldoctest
2088-
julia> replace([1, 2, 1, 3], 1, 0, 2)
2106+
julia> replace([1, 2, 1, 3], 1=>0, 2=>4; n=2)
20892107
4-element Array{Int64,1}:
20902108
0
2091-
2
2092-
0
2109+
4
2110+
1
20932111
3
20942112
```
20952113
"""
2096-
replace(A, old, new, n::Integer=typemax(Int)) = replace!(copy(A), old, new, n)
2114+
replace(A, old_new::Pair...; n::Integer=typemax(Int)) = replace!(copy(A), old_new..., n=n)
20972115

20982116
"""
2099-
replace(pred, A, new, [n])
2100-
replace(pred, f::Callable, A, [n])
2117+
replace(pred::Function, A, new; [n::Integer])
21012118
21022119
Return a copy of collection `A` where all occurrences `x` for which
2103-
`pred(x)` is true are replaced by `new` or `f(x)`.
2104-
If `n` is specified, then replace at most `n` occurrences.
2120+
`pred(x)` is true are replaced by `new`.
21052121
2106-
# Examples
2122+
# Example
21072123
```jldoctest
2108-
julia> replace(isodd, [1, 2, 3, 1], 0, 2)
2124+
julia> replace(isodd, [1, 2, 3, 1], 0, n=2)
21092125
4-element Array{Int64,1}:
21102126
0
21112127
2
21122128
0
21132129
1
2130+
```
2131+
2132+
replace(prednew::Function, A; [n::Integer])
2133+
2134+
Return a copy of `A` where for each value `x` in `A`, `prednew(x)` is called
2135+
and must return a `Nullable` object. If it is not null, then the wrapped
2136+
value will be used as a replacement for `x`.
21142137
2115-
julia> replace(x->x.first=>3, Dict(1=>2, 3=>4), 1) do kv
2116-
first(kv) < 3
2138+
julia> replace(Dict(1=>2, 3=>4)) do kv
2139+
Nullable(first(kv)=>3, first(kv) < 3)
21172140
end
21182141
Dict{Int64,Int64} with 2 entries:
21192142
3 => 4
21202143
1 => 3
21212144
```
21222145
21232146
"""
2124-
replace(pred::Callable, new::Callable, A, n::Integer=typemax(Int)) = replace!(pred, new, copy(A), n)
2125-
replace(pred::Callable, A, new, n::Integer=typemax(Int)) = replace!(pred, copy(A), new, n)
2147+
replace(prednew::Callable, A; n::Integer=typemax(Int)) = replace!(prednew, copy(A), n=n)
2148+
replace(pred::Callable, A, new; n::Integer=typemax(Int)) = replace!(pred, copy(A), new, n=n)

base/set.jl

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -357,20 +357,21 @@ convert(::Type{Set{T}}, x::Set) where {T} = Set{T}(x)
357357
askey(k, ::Associative) = k.first
358358
askey(k, ::AbstractSet) = k
359359

360-
function _replace!(pred::Callable, new::Callable, A::Union{Associative,AbstractSet}, n::Int)
360+
function _replace!(prednew::Callable, A::Union{Associative,AbstractSet}, n::Int)
361361
# precondition: n > 0
362-
del = eltype(A)[]
362+
repl = Pair{eltype(A),eltype(A)}[]
363363
count = 0
364364
for x in A
365-
if pred(x)
366-
push!(del, x)
365+
y = prednew(x)
366+
if !isnull(y)
367+
push!(repl, x=>get(y))
367368
count += 1
368369
count == n && break
369370
end
370371
end
371-
for k in del
372-
pop!(A, askey(k, A))
373-
push!(A, new(k))
372+
for oldnew in repl
373+
pop!(A, askey(first(oldnew), A))
374+
push!(A, last(oldnew))
374375
end
375376
A
376377
end

doc/src/stdlib/collections.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,8 @@ Base.collect(::Type, ::Any)
133133
Base.issubset(::Any, ::Any)
134134
Base.filter
135135
Base.filter!
136-
Base.replace(A, old, new, n::Integer)
137-
Base.replace(pred::Base.Callable, new::Base.Callable, A, n::Integer)
136+
# this also includes the docstring for replace(A, old, new, n)
137+
Base.replace(::Base.Callable, ::Base.Callable, ::Any)
138138
Base.replace!
139139
```
140140

test/arrayops.jl

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2152,28 +2152,28 @@ Base.:(==)(a::T11053, b::T11053) = a.a == b.a
21522152

21532153
@testset "replace! & replace" begin
21542154
a = [1, 2, 3, 1]
2155-
@test replace(iseven, x->2x, a) == [1, 4, 3, 1]
2156-
@test replace!(iseven, x->2x, a) === a
2155+
@test replace(x->Nullable(2x, iseven(x)), a) == [1, 4, 3, 1]
2156+
@test replace!(x->Nullable(2x, iseven(x)), a) === a
21572157
@test a == [1, 4, 3, 1]
2158-
@test replace(a, 1, 0) == [0, 4, 3, 0]
2159-
@test replace(a, 1, 0, 1) == [0, 4, 3, 1] # 1 replacement only
2160-
@test replace!(a, 1, 2) == [2, 4, 3, 2]
2158+
@test replace(a, 1=>0) == [0, 4, 3, 0]
2159+
@test replace(a, 1=>0, n=1) == [0, 4, 3, 1]
2160+
@test replace!(a, 1=>2) == [2, 4, 3, 2]
21612161

21622162
d = Dict(1=>2, 3=>4)
21632163
@test replace(x->x.first > 2, d, 0=>0) == Dict(1=>2, 0=>0)
2164-
@test replace!(x->x.first > 2, x->(x.first=>2*x.second), d) ==
2164+
@test replace!(x->Nullable(x.first=>2*x.second, x.first > 2), d) ==
21652165
Dict(1=>2, 3=>8)
2166-
@test replace(d, 3=>8, 0=>0) == Dict(1=>2, 0=>0)
2167-
@test replace!(d, 3=>8, 2=>2) === d
2166+
@test replace(d, (3=>8)=>(0=>0)) == Dict(1=>2, 0=>0)
2167+
@test replace!(d, (3=>8)=>(2=>2)) === d
21682168
@test d == Dict(1=>2, 2=>2)
2169-
@test replace(x->x.second == 2, d, 0=>0, 1) in [Dict(1=>2, 0=>0),
2170-
Dict(2=>2, 0=>0)]
2169+
@test replace(x->x.second == 2, d, 0=>0, n=1) in [Dict(1=>2, 0=>0),
2170+
Dict(2=>2, 0=>0)]
21712171

21722172
s = Set([1, 2, 3])
2173-
@test replace(x->x>1, x->2x, s) == Set([1, 4, 6])
2174-
@test replace(x->x>1, x->2x, s, 1) in [Set([1, 4, 3]), Set([1, 2, 6])]
2175-
@test replace(s, 1, 4) == Set([2, 3, 4])
2176-
@test replace!(s, 1, 2) == Set([2, 3])
2173+
@test replace(x->Nullable(2x, x>1), s) == Set([1, 4, 6])
2174+
@test replace(x->Nullable(2x, x>1), s, n=1) in [Set([1, 4, 3]), Set([1, 2, 6])]
2175+
@test replace(s, 1=>4) == Set([2, 3, 4])
2176+
@test replace!(s, 1=>2) == Set([2, 3])
21772177

2178-
@test !(0 in replace([1, 2, 3], 1, 0, 0)) # count=0 --> no replacements
2178+
@test 0 replace([1, 2, 3], 1=>0, n=0) # count=0 --> no replacements
21792179
end

0 commit comments

Comments
 (0)