如何获取字符串中字符出现的次数?
\documentclass[14pt]{extarticle}
\usepackage{xstring}
\usepackage{forloop}
\usepackage{ifthen}
\usepackage{pgfkeys}
\newcommand{\fios}{hellow world}
\begin{document}
%\StrCount{\fios}{e}
%\StrChar{\fios}{1}
\StrLen{\fios}[\varL]
\varL
\vspace{5ex}
\newcounter{loop}
\forloop{loop}{1}{\value{loop}< \varL}
{\StrChar{\fios}{\arabic{loop}}~--
\par
}
\end{document}
我需要得到:
h - 1
e - 1
l - 3
o - 2
w - 2
r - 1
d - 1
答案1
这是 Lua 代码片段,字符串中有一些 CJKV 字符。我从 TeX Live 中选择了一种 opentype 字体,但它不包含一些变音字母(例如 č、ř 和 š),希望它足以作为处理 UTF-8 字符串的演示。我们运行lualatex mal-letters.tex
。
% lualatex mal-letters.tex
\documentclass[a4paper]{article}
\pagestyle{empty}
\parindent=0pt
\usepackage{luacode} % to be able to write Lua code
\usepackage{fontspec} % to be able to load fonts (CJKV)
\begin{document}
\begin{luacode*}
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
end -- function, countme
\end{luacode*}
\def\occurs#1{\toks0{#1}\directlua{countme()}}
% This particular font doesn't contain č, ř, š etc., but it does contain CJKV.
\occurs{你怎么样? Pavel Stříž, číšník. さよなら。}
\end{document}
在终端中,我们会发现与此类似的结构:
ž 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
4
í 3
e 1
v 1
S 1
t 1
答案2
使用 xstring 进行编程很容易(没有无用的测试):
\documentclass{extarticle}
\usepackage{xstring}
\newcommand\fios{hellow world}
\newcommand\occurs[1]{%
\ifhmode\par\fi\begingroup\expandarg
\StrDel{#1}{ }[\tempstr]%
\occuraux\endgroup
}
\newcommand\occuraux{%
\unless\ifx\tempstr\empty
\StrSplit\tempstr1\currentchar\remainstr
\currentchar\space-- \StrCount\tempstr\currentchar\par
\let\tempstr\remainstr
\StrDel\tempstr\currentchar[\tempstr]%
\expandafter\occuraux
\fi
}
\begin{document}
\occurs{hello world}
\bigskip
\occurs\fios
\end{document}
答案3
使用expl3
和l3regex
:
\documentclass{article}
\usepackage{xparse,l3regex}
\ExplSyntaxOn
\NewDocumentCommand{\countchar}{mm}
{% #1 = character, #2 = string
\youra_count_char:nn { #1 } { #2 }
\int_to_arabic:n { \l_youra_count_char_int }
}
\NewDocumentCommand{\countallchars}{m}
{% #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
{
\par
\youra_count_char:nn { ##1 } { #1 }
##1 ~ - ~ \int_to_arabic:n { \l_youra_count_char_int }
\par
}
}
\ExplSyntaxOff
\begin{document}
\countchar{h}{hello world}
\countallchars{hello world}
\end{document}
单字符版本仅使用\regex_count:nnN
并传递获得的结果;完整版本将字符串按序列拆分,删除重复项和可能的空格,然后映射序列以对每个项目进行计数。
答案4
这里,使用stringstrings
包,我提供了两个版本:一个按字母顺序计数(\countstring
),另一个按出现顺序计数(\Countstring
)。
\documentclass{article}
\usepackage{stringstrings}
\def\countstring#1{%
\caselower[q]{#1}%
\testchar{\thestring}{a}\testchar{\thestring}{b}\testchar{\thestring}{c}%
\testchar{\thestring}{d}\testchar{\thestring}{e}\testchar{\thestring}{f}%
\testchar{\thestring}{g}\testchar{\thestring}{h}\testchar{\thestring}{i}%
\testchar{\thestring}{j}\testchar{\thestring}{k}\testchar{\thestring}{l}%
\testchar{\thestring}{m}\testchar{\thestring}{n}\testchar{\thestring}{o}%
\testchar{\thestring}{p}\testchar{\thestring}{q}\testchar{\thestring}{r}%
\testchar{\thestring}{s}\testchar{\thestring}{t}\testchar{\thestring}{u}%
\testchar{\thestring}{v}\testchar{\thestring}{w}\testchar{\thestring}{x}%
\testchar{\thestring}{y}\testchar{\thestring}{z}%
}
\def\testchar#1#2{%
\findchars[q]{#1}{#2}\ifnum\theresult>0\par\noindent#2 - \theresult\par\fi}
\def\Countstring#1{\caselower[q]{#1}\expandafter\Countstringhelp\thestring\relax}
\def\Countstringhelp#1#2\relax{%
\ifcsname #1Chars\endcsname\else%
\testchar{\thestring}{#1}%
\ifnum\theresult>0\relax\expandafter\def\csname #1Chars\endcsname{\theresult}\fi%
\fi
\ifx\relax#2\else\Countstringhelp#2\relax\fi%
}
\begin{document}
\countstring{Hellow World}
\noindent\hrulefill
\Countstring{Hellow World}
\end{document}