
Esta preguntamuestra cómo contar el número de apariciones de un carácter específico en una cadena. Me gustaría hacerlo de forma ampliable y para obtener una lista (no solo uno) de personajes específicos.
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewExpandableDocumentCommand{\countsep}{r[] m}{
% CODE HERE
}
\ExplSyntaxOff
\begin{document}
\countsep[-+]{This-is-a+test} % Count the number of - and + in the string (3)
\countsep[-+]{T+h+i+s-is-a-test} % Count the number of - and + in the string (6)
\end{document}
Respuesta1
\documentclass{article}
\def\countsep#1#2{\the\numexpr0\countsepy#1\Endlist#2\Endcount}
\def\countsepy#1#2\Endlist#3\Endcount{\countsepz#1#3\Endcount
\ifx\relax#2\relax\relax\else\countsepy#2\Endlist#3\Endcount\fi}
\def\countsepz#1#2#3\Endcount{\ifx#1#2+1\fi
\ifx\relax#3\relax\else\countsepz#1#3\Endcount\fi}
\begin{document}
\countsep{-}{This-is-a+test} % Count the number of - in the string (2)
\countsep{+}{This-is-a+test} % Count the number of + in the string (1)
\countsep{-+}{This-is-a+test} % Count the number of - and + in the string (3)
\edef\z{\countsep{-+}{T+h+i+s-is-a-test}}
\z
\end{document}
Respuesta2
Aquí hay una solución basada en LuaLaTeX para \countsep
. La solución es un simple refinamiento de unsoluciónle di a laconsulta anteriormencionado en la publicación del OP. Tenga en cuenta que \countsep
es ampliable porque \directlua
y \luastring
son ampliables.
Observe además que tanto la cadena de búsqueda como la cadena de destino pueden incluir caracteres generales codificados en UTF8.
% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{luacode} % for '\luastring' macro
\newcommand\countsep[2]{\directlua{%
_ , count = unicode.utf8.gsub ( "#2" , "["..\luastring{#1}.."]" , "" )
tex.sprint ( count ) }}
\def\yy{äÖÜß}
\def\zz{ßT+h+i+s-is-a-testäÖÜß}
\edef\z{\countsep{\yy}{\zz}}
\begin{document}
\countsep{""}{This-is-a+test} % result: 0
\countsep{-+}{This-is-a+test} % result: 3
\countsep{-+}{T+h+i+s-is-a-test} % result: 6
\countsep{\yy}{\zz\zz} % result: 10
\z % result: 5
\end{document}
Respuesta3
Lo siguiente implementa esto en L3 usando etl
. Utiliza el argumento requerido entre paréntesis de su pregunta, aunque lo desaconsejo encarecidamente. Se desaconseja el uso de argumentos no estándar por una razón, []
generalmente es un argumento opcional, lo cual no lo es, y no veo ninguna buena razón para la sobrecarga de análisis aquí.
Cosas para mencionar:
- esto supone que realmente desea contar las ocurrencias en una lista de tokens (sin cadenas)
- esto supone que los separadores dentro de las llaves deben contarse (si no, cambie el anidado
+ \vincent_count_tokens_in:nn
a\use_none:nn
) - Esto cuenta correctamente si uno de los separadores especificados es un espacio
- Esto no funciona para símbolos separadores que no sean ASCII en motores que no sean UTF8 (pdfTeX); de lo contrario, funciona en todos los motores.
\documentclass{article}
\usepackage{xparse, etl}
\ExplSyntaxOn
\etl_new_if_in:Nnn \__vincent_if_contains_space:n { ~ } { T }
\cs_new:Npn \vincent_count_tokens_in:nn #1#2
{
\int_eval:w 0
\etl_act:nennn
\__vincent_count_tokens_in:nN
{
\__vincent_if_contains_space:nT {#1} { + \c_one_int }
\use_none:n
}
{ + \vincent_count_tokens_in:nn }
{#1}
{#2}
\scan_stop:
}
\cs_generate_variant:Nn \etl_act:nnnnn { ne }
\cs_new:Npn \__vincent_count_tokens_in:nN #1#2
{ \etl_token_if_in:nNT {#1} #2 { + \c_one_int } }
\NewExpandableDocumentCommand{\countsep}{r[] m}
{ \vincent_count_tokens_in:nn {#1} {#2} }
\ExplSyntaxOff
\begin{document}
\countsep[-+]{This-is-a+test} % Count the number of - and + in the string (3)
\countsep[- +]{T+h+i+s is{-a-}test} % Count the number of -, space and + in the string (6)
\end{document}
Aparte: esto no es particularmente rápido, ya que etl
tiene que verificar espacios y grupos para cada elemento de la lista, por lo que hace mucho más en segundo plano que la solución de @StevenB.Segletes, esto solo es necesario si realmente desea poder contar espacios y/o recurrir a grupos.