Skip to content

Commit

Permalink
Accept AbstractChar in count and findall (::Char, ::String) (JuliaLan…
Browse files Browse the repository at this point in the history
…g#38675)

This change solves an issue raised in this post, in which searching for a char in a string results in a Method error: https://discourse.julialang.org/t/method-for-counting-characters-in-string-count-a-batman-vs-count-a-batman/51153

Co-authored-by: Stefan Karpinski <[email protected]>
Co-authored-by: Steven G. Johnson <[email protected]>
  • Loading branch information
3 people committed Dec 11, 2020
1 parent 3d3cf1b commit 26b73d6
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 3 deletions.
2 changes: 1 addition & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Julia v1.7 Release Notes

New language features
---------------------

* `count` and `findall` now accept an `AbstractChar` argument to search for a character in a string ([#38675]).

Language changes
----------------
Expand Down
27 changes: 25 additions & 2 deletions base/regex.jl
Original file line number Diff line number Diff line change
Expand Up @@ -396,9 +396,29 @@ function findall(t::Union{AbstractString,AbstractPattern}, s::AbstractString; ov
return found
end

"""
findall(c::AbstractChar, s::AbstractString)
Return a vector `I` of the indices of `s` where `s[i] == c`. If there are no such
elements in `s`, return an empty array.
# Examples
```jldoctest
julia> findall('a', "batman")
2-element Vector{Int64}:
2
5
```
!!! compat "Julia 1.7"
This method requires at least Julia 1.7.
"""
findall(c::AbstractChar, s::AbstractString) = findall(isequal(c),s)


"""
count(
pattern::Union{AbstractString,AbstractPattern},
pattern::Union{AbstractChar,AbstractString,AbstractPattern},
string::AbstractString;
overlap::Bool = false,
)
Expand All @@ -411,8 +431,11 @@ original string, otherwise they must be from disjoint character ranges.
!!! compat "Julia 1.3"
This method requires at least Julia 1.3.
!!! compat "Julia 1.7"
Using a character as the pattern requires at least Julia 1.7.
"""
function count(t::Union{AbstractString,AbstractPattern}, s::AbstractString; overlap::Bool=false)
function count(t::Union{AbstractChar,AbstractString,AbstractPattern}, s::AbstractString; overlap::Bool=false)
n = 0
i, e = firstindex(s), lastindex(s)
while true
Expand Down
10 changes: 10 additions & 0 deletions test/regex.jl
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,22 @@
@test findall(r"\w+", "foo bar", overlap=true) == [1:3, 2:3, 3:3, 5:7, 6:7, 7:7]
@test all(findall(r"\w*", "foo bar") .=== [1:3, 4:3, 5:7, 8:7]) # use === to compare empty ranges
@test all(findall(r"\b", "foo bar") .=== [1:0, 4:3, 5:4, 8:7]) # use === to compare empty ranges
# with Char as argument
@test findall('a', "batman") == [2, 5]
@test findall('', "OH⁻ + H₃CBr → HOH₃CBr⁻ → HOCH₃ + Br⁻") == [17, 35]
@test findall('a', "") == Int[]
@test findall('c', "batman") == Int[]

# count
@test count(r"\w+", "foo bar") == 2
@test count(r"\w+", "foo bar", overlap=true) == 6
@test count(r"\w*", "foo bar") == 4
@test count(r"\b", "foo bar") == 4
# count with char as argument
@test count('a', "batman") == 2
@test count('a', "aaa", overlap=true) == 3
@test count('a', "") == 0
@test count('', "OH⁻ + H₃CBr → (HOH₃CBr⁻)† → HOCH₃ + Br⁻") == 2

# Unnamed subpatterns
let m = match(r"(.)(.)(.)", "xyz")
Expand Down

0 comments on commit 26b73d6

Please sign in to comment.