Last active
August 29, 2015 14:17
-
-
Save nalimilan/7e494b97212286b44daf to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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