From 9ef327d0694e7c0e09071cf5d4a4889e4728ecde Mon Sep 17 00:00:00 2001 From: Milan Bouchet-Valat Date: Sun, 21 Jun 2015 15:39:15 +0200 Subject: [PATCH] Add eachindex() for AbstractStrings and Associative There's no reason not to allow this. Fixes #11649. --- base/dict.jl | 1 + base/string.jl | 11 +++++++++++ doc/stdlib/arrays.rst | 4 +++- test/dict.jl | 5 +++++ test/strings.jl | 5 +++++ 5 files changed, 25 insertions(+), 1 deletion(-) diff --git a/base/dict.jl b/base/dict.jl index 5da08ef45d802..5b714b55cb5cc 100644 --- a/base/dict.jl +++ b/base/dict.jl @@ -192,6 +192,7 @@ in(k, v::KeyIterator) = !is(get(v.dict, k, secret_table_token), secret_table_token) keys(a::Associative) = KeyIterator(a) +eachindex(a::Associative) = KeyIterator(a) values(a::Associative) = ValueIterator(a) function copy(a::Associative) diff --git a/base/string.jl b/base/string.jl index 1542296b8280d..c1740163b0543 100644 --- a/base/string.jl +++ b/base/string.jl @@ -181,6 +181,17 @@ function chr2ind(s::AbstractString, i::Integer) end end +immutable EachStringIndex{T<:AbstractString} + s::T +end +eachindex(s::AbstractString) = EachStringIndex(s) + +length(e::EachStringIndex) = length(e.s) +start(e::EachStringIndex) = start(e.s) +next(e::EachStringIndex, state) = (state, nextind(e.s, state)) +done(e::EachStringIndex, state) = done(e.s, state) +eltype(e::EachStringIndex) = Int + typealias Chars Union{Char,AbstractVector{Char},Set{Char}} function search(s::AbstractString, c::Chars, i::Integer) diff --git a/doc/stdlib/arrays.rst b/doc/stdlib/arrays.rst index 4cde84a8baf3a..33614d302674f 100644 --- a/doc/stdlib/arrays.rst +++ b/doc/stdlib/arrays.rst @@ -33,7 +33,9 @@ Basic functions .. function:: eachindex(A...) - Creates an iterable object for visiting each index of an AbstractArray ``A`` in an efficient manner. For array types that have opted into fast linear indexing (like ``Array``), this is simply the range ``1:length(A)``. For other array types, this returns a specialized Cartesian range to efficiently index into the array with indices specified for every dimension. Example for a sparse 2-d array:: + Creates an iterable object for visiting each index of an AbstractArray ``A`` in an efficient manner. For array types that have opted into fast linear indexing (like ``Array``), this is simply the range ``1:length(A)``. For other array types, this returns a specialized Cartesian range to efficiently index into the array with indices specified for every dimension. For other iterables, including strings and dictionaries, this returns an iterator object supporting arbitrary index types (e.g. unevenly spaced or non-integer indices). + + Example for a sparse 2-d array:: julia> A = sprand(2, 3, 0.5) 2x3 sparse matrix with 4 Float64 entries: diff --git a/test/dict.jl b/test/dict.jl index 53e39b8870638..009ae29e2e3c3 100644 --- a/test/dict.jl +++ b/test/dict.jl @@ -333,3 +333,8 @@ let d = Dict{Int,Int}() end @test length(d) == 1 end + +# iteration +d = Dict('a'=>1, 'b'=>1, 'c'=> 3) +@test [d[k] for k in keys(d)] == [d[k] for k in eachindex(d)] == + [v for (k, v) in d] == [d[x[1]] for (i, x) in enumerate(d)] diff --git a/test/strings.jl b/test/strings.jl index 3215e140f1a2c..3701567bae68e 100644 --- a/test/strings.jl +++ b/test/strings.jl @@ -1892,3 +1892,8 @@ end @test_throws BoundsError Base.checkstring(b"abcdef", 3, 0) @test_throws BoundsError Base.checkstring(b"abcdef", 3, 7) @test_throws ArgumentError Base.checkstring(b"abcdef", 3, 1) + +# iteration +@test [c for c in "ḟøøƀäṙ"] == ['ḟ', 'ø', 'ø', 'ƀ', 'ä', 'ṙ'] +@test [i for i in eachindex("ḟøøƀäṙ")] == [1, 4, 6, 8, 10, 12] +@test [x for x in enumerate("ḟøøƀäṙ")] == [(1, 'ḟ'), (2, 'ø'), (3, 'ø'), (4, 'ƀ'), (5, 'ä'), (6, 'ṙ')]