'Getting count of occurrences for X in string

Im looking for a function like Pythons

"foobar, bar, foo".count("foo")

Could not find any functions that seemed able to do this, in a obvious way. Looking for a single function or something that is not completely overkill.



Solution 1:[1]

I think that right now the closest built-in thing to what you're after is the length of a split (minus 1). But it's not difficult to specifically create what you're after.

I could see a searchall being generally useful in Julia's Base, similar to matchall. If you don't care about the actual indices, you could just use a counter instead of growing the idxs array.

function searchall(s, t; overlap::Bool=false)
    idxfcn = overlap ? first : last
    r = findnext(s, t, firstindex(t))
    idxs = typeof(r)[] # Or to only count: n = 0
    while r !== nothing
        push!(idxs, r) # n += 1
        r = findnext(s, t, idxfcn(r) + 1)
    end
    idxs # return n
end

Solution 2:[2]

Julia-1.0 update:

For single-character count within a string (in general, any single-item count within an iterable), one can use Julia's count function:

julia> count(i->(i=='f'), "foobar, bar, foo")
2

(The first argument is a predicate that returns a ::Bool).

For the given example, the following one-liner should do:

julia> length(collect(eachmatch(r"foo", "bar foo baz foo")))
2

Julia-1.7 update:

Starting with Julia-1.7 Base.Fix2 can be used, through ==('f') below, as to shorten and sweeten the syntax:

julia> count(==('f'), "foobar, bar, foo")
2

Solution 3:[3]

What about regexp ?

julia> length(matchall(r"ba", "foobar, bar, foo"))
2

Solution 4:[4]

Adding an answer to this which allows for interpolation:

julia> a = ", , ,";
julia> b = ",";
julia> length(collect(eachmatch(Regex(b), a)))
3

Actually, this solution breaks for some simple cases due to use of Regex. Instead one might find this useful:

"""
count_flags(s::String, flag::String)

counts the number of flags `flag` in string `s`.
"""
function count_flags(s::String, flag::String)
counter = 0
for i in 1:length(s)
  if occursin(flag, s)
    s = replace(s, flag=> "", count=1)
    counter+=1
  else
    break
  end
end
return counter
end

Solution 5:[5]

Sorry to post another answer instead of commenting previous one, but i've not managed how to deal with code blocks in comments :)

If you don't like regexps, maybe a tail recursive function like this one (using the search() base function as Matt suggests) :

function mycount(what::String, where::String)
  function mycountacc(what::String, where::String, acc::Int)
    res = search(where, what)
    res == 0:-1 ? acc : mycountacc(what, where[last(res) + 1:end], acc + 1)
  end
  what == "" ? 0 : mycountacc(what, where, 0)
end

Solution 6:[6]

This is simple and fast (and does not overflow the stack):

function mycount2(where::String, what::String)
    numfinds = 0
    starting = 1
    while true
        location = search(where, what, starting)
        isempty(location) && return numfinds
        numfinds += 1
        starting = location.stop + 1
    end
end

Solution 7:[7]

one liner: (Julia 1.3.1):

julia> sum([1 for i = eachmatch(r"foo", "foobar, bar, foo")])
2

Solution 8:[8]

Since Julia 1.3, there has been a count method that does exactly this.

  count(
      pattern::Union{AbstractChar,AbstractString,AbstractPattern},
      string::AbstractString;
      overlap::Bool = false,
  )

  Return the number of matches for pattern in string.  
  This is equivalent to calling length(findall(pattern, string)) but more
  efficient.

  If overlap=true, the matching sequences are allowed to overlap indices in the
  original string, otherwise they must be from disjoint character ranges.

  ? Julia 1.3
  ?
  ?  This method requires at least Julia 1.3.
julia> count("foo", "foobar, bar, foo") 
2

julia> count("ana", "bananarama")
1

julia> count("ana", "bananarama", overlap=true)
2

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 jaco
Solution 4
Solution 5
Solution 6
Solution 7 root-11
Solution 8 Sundar R