Skip to content

Instantly share code, notes, and snippets.

@nalimilan
Last active August 29, 2015 14:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nalimilan/7e494b97212286b44daf to your computer and use it in GitHub Desktop.
Save nalimilan/7e494b97212286b44daf to your computer and use it in GitHub Desktop.
VERSION < v"0.4-" && using Docile
VERSION < v"0.4-" && typealias Pair Tuple
@doc doc"""
recode!(dest::AbstractArray, source::AbstractArray, pairs::Pair...; default=Nullable())
Fill `dest` with elements from `source`, replacing those matching a key of `pairs`
with the corresponding value.
For each `Pair` in `pairs`, if the element is equal to (according to `==`) or `in` the key
(first item of the pair), then the corresponding value (second item) is copied to `source`.
If the element matches no key and `default` is `nothing` (the default), it is copied as-is;
if `default` is set to a different value, it is used instead of the original element.
Set `default=error()` if you want to ensure all elements match at least one key.
`dest` and `source` must be of the same length, but not necessarily of the same type.
Elements of `source` as well as values from `pairs` will be `convert`ed when possible
on assignment.
If an element matches more than one key, the first match is used.
""" ->
function recode!(dest::AbstractArray, source::AbstractArray, pairs::Pair...; default=nothing)
length(dest) == length(source) ||
error("dest and source must be of the same length (got $(length(dest)) and $(length(source)))")
lens = [length(v[1]) for v in pairs]
for i in 1:length(dest)
for j in 1:length(pairs)
p = pairs[j]
if (lens[j] == 1 && source[i] == p[1]) ||
(lens[j] > 1 && source[i] in p[1])
dest[i] = p[2]
@goto nextitem
end
end
# Value not in any of the pairs
dest[i] = ifelse(default == nothing, source[i], default)
@label nextitem
end
dest
end
@doc doc"""
recode!(a::AbstractArray, pairs::Pair...; default=nothing)
Convenience function for in-place recoding, equivalent to `recode!(a, a, ...)`.
**Example:**
```julia
julia> x = collect(1:10);
julia> recode!(x, 1=>100, 2:4=>0, [5, 9:10]=>-1);
julia> x
10-element Array{Int64,1}:
100
0
0
0
-1
6
7
8
-1
-1
```
"""
recode!(a::AbstractArray, pairs::Pair...; default=nothing) = recode!(a, a, pairs...; default=default)
@doc doc"""
recode(source::AbstractArray, pairs::Pair...; default=nothing)
Return a new `Array` with elements from `a`, replacing elements matching a key
of `pairs` with the corresponding value. The type of the array is chosen using `promote`
so that it can hold all elements from `a` as well as replaced elements.
For each `Pair` in `pairs`, if the element is equal to (according to `==`) or `in` the key
(first item of the pair), then the corresponding value (second item) is used.
If the element matches no key and `default` is `nothing` (the default), it is copied as-is;
if `default` is set to a different value, it is used instead of the original element.
Set `default=error()` if you want to ensure all elements match at least one key.
If an element matches more than one key, the first match is used.
**Example:**
```julia
julia> recode(1:10, 1=>100, 2:4=>0, [5, 9:10]=>-1)
10-element Array{Int64,1}:
100
0
0
0
-1
6
7
8
-1
-1
```
""" ->
function recode(source::AbstractArray, pairs::Pair...; default=nothing)
T = reduce(promote_type, ntuple(length(pairs), i -> typeof(pairs[i][2])))
T = default == nothing ? promote_type(T, eltype(source)) :
promote_type(T, typeof(default))
dest = similar(source, T)
recode!(dest, source, pairs...; default=default)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment