How to get the number of occurrences of characters in a string?

\newcommand{\fios}{hellow world}

\forloop{loop}{1}{\value{loop}< \varL}

I need to get:

h - 1
e - 1
l - 3
o - 2
w - 2
r - 1
d - 1

5 Answers 5


This is a Lua snippet with some CJKV characters in the strings. I've selected an opentype font from TeX Live, but it doesn't contain some diacritical letters (e.g. č, ř and š), let me hope it is sufficient as a demonstration of handling UTF-8 strings. We run lualatex mal-letters.tex.

% lualatex mal-letters.tex
\usepackage{luacode} % to be able to write Lua code
\usepackage{fontspec} % to be able to load fonts (CJKV)

chars={} -- Lua table to store occurencies
function countme() -- the core function
text=tex.toks[0] -- pass an argument from TeX
unicode.utf8.gsub(text, ".", function(s) -- find any utf8 char
   if not chars[s] then chars[s]=0 end -- define it if it is not
   chars[s]=chars[s]+1 -- plus one as a char has been found
   return s -- don't change an original string
   end) -- end of function and gsub
-- print the results to the terminal
for letter,count in pairs(chars) do
   print(letter, count)
   -- comment out the following line, if you don't have that font (texmf-dist/fonts/opentype/public/fandol/fandolsong-regular.otf) and check out the terminal
   tex.print("{\\setmainfont{FandolSong}"..letter.."} ("..count..");")
end -- function, countme
% This particular font doesn't contain č, ř, š etc., but it does contain CJKV.
\occurs{你怎么样? Pavel Stříž, číšník. さよなら。}

An example working with CJKV characters

In the terminal, we will spot a similar structure to this one:

ž   1
?   1
你   1
么   1
。   1
な   1
,   1
怎   1
a   1
さ   1
.   1
k   1
样   1
ら   1
P   1
š   1
n   1
č   1
l   1
ř   1
よ   1
í   3
e   1
v   1
S   1
t   1

It is easy to program with xstring (with no unuseful test):

\newcommand\fios{hellow world}
    \StrDel{#1}{ }[\tempstr]%
        \currentchar\space-- \StrCount\tempstr\currentchar\par
\occurs{hello world}


enter image description here


With expl3 and l3regex:


 {% #1 = character, #2 = string
  \youra_count_char:nn { #1 } { #2 }
  \int_to_arabic:n { \l_youra_count_char_int }

 {% #1 = string
  \youra_count_all_chars:n { #1 }

\int_new:N \l_youra_count_char_int
\seq_new:N \l_youra_count_chars_seq

\cs_new_protected:Npn \youra_count_char:nn #1 #2
  \regex_count:nnN { #1 } { #2 } \l_youra_count_char_int

\cs_new_protected:Npn \youra_count_all_chars:n #1
  \seq_set_split:Nnn \l_youra_count_chars_seq { } { #1 }
  \seq_remove_duplicates:N \l_youra_count_chars_seq
  \seq_remove_all:Nn \l_youra_count_chars_seq { ~ }
  \seq_map_inline:Nn \l_youra_count_chars_seq
    \youra_count_char:nn { ##1 } { #1 }
    ##1 ~ - ~ \int_to_arabic:n { \l_youra_count_char_int }



\countchar{h}{hello world}

\countallchars{hello world}


enter image description here

The single character version just uses \regex_count:nnN and delivers the result obtained; the full version splits the string in a sequence, removes the duplicates and possible spaces, then maps the sequence to do the counting for each item.


Here is a non-package solution. It lists the found letters in alphabetical order. It also works fine with pdftex and any traditional 8bit encoding. Not designed for Unicode !

Make sure to save the code sample in iso-latin-1 encoding (automatic if you copy paste to an Emacs buffer due to the magic line at top).

% -*- coding: latin-1; -*-

% Time-stamp: <28-03-2015 14:04:16 CET>

\usepackage[latin1]{inputenc}% THIS CODE ONLY FOR SOME 8bit ENCODING

\newcommand*\countchars [1]{%
    Here is (in alphabetical order) the count of characters in \emph{#1}:\par
    \let\countchars@list \@empty
    \expandafter\countchars@i\detokenize{#1}\relax }

\def\countchars@i #1{%
    \if\relax #1\expandafter\countchars@print\fi
    \expandafter\countchars@seek\expandafter #1\countchars@list a\relax a%

\def\countchars@seek #1#2a#3a{%
    \if\relax #3\expandafter\countchars@seekend\fi
            {\countchars@list #1a1a#2a#3a}%
            \expandafter#2\expandafter a\the\numexpr #3+\@ne a}%
          {\countchars@list #2a#3a}%
    \countchars@seek #1%

\def\countchars@endseek\countchars@seek #1#2a\relax a{%
     \def\expandafter\countchars@list\expandafter {\countchars@list #2}%

\def\countchars@seekend #1\countchars@seek #2{%
    \def\expandafter\countchars@list\expandafter {\countchars@list #2a1a}%

\def\countchars@print #1a\relax a{\count@ \z@
    \expandafter\countchars@printi\countchars@list a\relax a}

\def\countchars@printi #1a#2a{\if \relax #2\expandafter\countchars@end\fi
    \makebox[2em]{\scantokens{#1}}: #2\par
    \advance\count@ #2\relax
\long\def\countchars@end #1\countchars@printi {There were altogether
  \the\count@{} non space characters found.}     



\countchars{Hello World}


\countchars{La République assure la liberté de conscience. Elle garantit le
  libre exercice des cultes sous les seules restrictions édictées ci-après
  dans l'intérêt de l'ordre public.}


enter image description here

  • if word counting is needed (in the sense of counting things separated by spaces) this can be added too.
    – user4686
    Commented Mar 28, 2015 at 13:36

Here, using stringstrings package, I provide two versions: one that counts it alphabetically (\countstring), and the next that counts in the order of appearance (\Countstring).

  \findchars[q]{#1}{#2}\ifnum\theresult>0\par\noindent#2 - \theresult\par\fi}
  \ifcsname #1Chars\endcsname\else%
    \ifnum\theresult>0\relax\expandafter\def\csname #1Chars\endcsname{\theresult}\fi%
\countstring{Hellow World}
\Countstring{Hellow World}

enter image description here

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .