Contar el número de apariciones de caracteres específicos en una cadena de forma ampliable

Contar el número de apariciones de caracteres específicos en una cadena de forma ampliable

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}

ingrese la descripción de la imagen aquí

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 \countsepes ampliable porque \directluay \luastringson ampliables.

Observe además que tanto la cadena de búsqueda como la cadena de destino pueden incluir caracteres generales codificados en UTF8.

ingrese la descripción de la imagen aquí

% !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:nna \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 etltiene 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.

información relacionada