Skip to content

Commit

Permalink
fix #15723, findfirst on strings
Browse files Browse the repository at this point in the history
Makes findfirst, findlast, findnext, and findprev more generic
by using endof, nextind, and prevind. Also adds a `nextind` method
for arrays and `CartesianIndex`.
  • Loading branch information
JeffBezanson committed Sep 5, 2017
1 parent 54b99d0 commit 908ead0
Show file tree
Hide file tree
Showing 6 changed files with 42 additions and 10 deletions.
3 changes: 3 additions & 0 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ linearindices(A::AbstractVector) = (@_inline_meta; indices1(A))
keys(a::AbstractArray) = CartesianRange(indices(a))
keys(a::AbstractVector) = linearindices(a)

prevind(::AbstractArray, i::Integer) = Int(i)-1
nextind(::AbstractArray, i::Integer) = Int(i)+1

eltype(::Type{<:AbstractArray{E}}) where {E} = E
elsize(::AbstractArray{T}) where {T} = sizeof(T)

Expand Down
31 changes: 23 additions & 8 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1621,10 +1621,13 @@ julia> findnext(A,3)
```
"""
function findnext(A, start::Integer)
for i = start:length(A)
l = endof(A)
i = start
while i <= l
if A[i] != 0
return i
end
i = nextind(A, i)
end
return 0
end
Expand Down Expand Up @@ -1671,10 +1674,13 @@ julia> findnext(A,4,3)
```
"""
function findnext(A, v, start::Integer)
for i = start:length(A)
l = endof(A)
i = start
while i <= l
if A[i] == v
return i
end
i = nextind(A, i)
end
return 0
end
Expand Down Expand Up @@ -1720,10 +1726,13 @@ julia> findnext(isodd, A, 2)
```
"""
function findnext(testf::Function, A, start::Integer)
for i = start:length(A)
l = endof(A)
i = start
while i <= l
if testf(A[i])
return i
end
i = nextind(A, i)
end
return 0
end
Expand Down Expand Up @@ -1770,8 +1779,10 @@ julia> findprev(A,1)
```
"""
function findprev(A, start::Integer)
for i = start:-1:1
i = start
while i >= 1
A[i] != 0 && return i
i = prevind(A, i)
end
return 0
end
Expand Down Expand Up @@ -1801,7 +1812,7 @@ julia> findlast(A)
0
```
"""
findlast(A) = findprev(A, length(A))
findlast(A) = findprev(A, endof(A))

"""
findprev(A, v, i::Integer)
Expand All @@ -1823,8 +1834,10 @@ julia> findprev(A, 1, 1)
```
"""
function findprev(A, v, start::Integer)
for i = start:-1:1
i = start
while i >= 1
A[i] == v && return i
i = prevind(A, i)
end
return 0
end
Expand Down Expand Up @@ -1875,8 +1888,10 @@ julia> findprev(isodd, A, 3)
```
"""
function findprev(testf::Function, A, start::Integer)
for i = start:-1:1
i = start
while i >= 1
testf(A[i]) && return i
i = prevind(A, i)
end
return 0
end
Expand All @@ -1901,7 +1916,7 @@ julia> findlast(x -> x > 5, A)
0
```
"""
findlast(testf::Function, A) = findprev(testf, A, length(A))
findlast(testf::Function, A) = findprev(testf, A, endof(A))

"""
find(f::Function, A)
Expand Down
6 changes: 6 additions & 0 deletions base/multidimensional.jl
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,12 @@ module IteratorsMD
return h
end

# nextind with CartesianIndex
function Base.nextind(a::AbstractArray{<:Any,N}, i::CartesianIndex{N}) where {N}
_, ni = next(CartesianRange(indices(a)), i)
return ni
end

# Iteration
"""
CartesianRange(sz::Dims) -> R
Expand Down
2 changes: 0 additions & 2 deletions base/strings/basic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,7 @@ end
## Generic indexing functions ##

prevind(s::DirectIndexString, i::Integer) = Int(i)-1
prevind(s::AbstractArray , i::Integer) = Int(i)-1
nextind(s::DirectIndexString, i::Integer) = Int(i)+1
nextind(s::AbstractArray , i::Integer) = Int(i)+1

"""
prevind(str::AbstractString, i::Integer)
Expand Down
4 changes: 4 additions & 0 deletions test/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -844,3 +844,7 @@ for A in (rand(2), rand(2,3))
end
@test collect(values(A)) == collect(A)
end

# nextind
@test nextind(zeros(4), 2) == 3
@test nextind(zeros(2,3), CartesianIndex(2,1)) == CartesianIndex(1, 2)
6 changes: 6 additions & 0 deletions test/strings/search.jl
Original file line number Diff line number Diff line change
Expand Up @@ -379,3 +379,9 @@ end
@test rsearchindex("\U1f596\U1f596", "\U1f596\U1f596", endof("\U1f596\U1f596\U1f596")) == 1

@test_throws ErrorException "ab" "abc"

# issue #15723
@test findfirst("⨳(", '(') == 4
@test findnext("(⨳(", '(', 2) == 5
@test findlast("(⨳(", '(') == 5
@test findprev("(⨳(", '(', 2) == 1

0 comments on commit 908ead0

Please sign in to comment.