文字列内の特定の文字の出現回数を拡張可能な方法でカウントする

文字列内の特定の文字の出現回数を拡張可能な方法でカウントする

この質問文字列内の特定の文字の出現回数をカウントする方法を示します。これを拡張可能な方法で、特定の文字のリスト (1 つだけではなく) に対して実行したいと思います。

\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}

答え1

\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}

ここに画像の説明を入力してください

答え2

これはLuaLaTeXベースのソリューションです\countsep。このソリューションは、解決私は以前のクエリOP の投稿で言及されています。 と は\countsep拡張可能であるため\directlua、 は\luastring拡張可能であることに注意してください。

さらに、検索文字列とターゲット文字列の両方に、一般的な 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}

答え3

以下は、 を使用して L3 でこれを実装しますetl。質問の括弧内の必須引数は使用しますが、私はそれを強くお勧めしません。非標準引数の使用は、理由があって推奨されません。は[]通常オプションの引数ですが、これはオプションではありません。また、ここでの解析オーバーヘッドに正当な理由は見当たりません。

言及すべき事項:

  • これは、トークンリスト内の出現回数を実際にカウントすることを前提としています(文字列化なし)
  • これは中括弧内の区切り文字がカウントされることを前提としています(そうでない場合はネスト+ \vincent_count_tokens_in:nnを に変更します\use_none:nn
  • 指定された区切り文字の1つがスペースの場合、これは正しくカウントされます。
  • これは、UTF8以外のエンジン(pdfTeX)の非ASCII区切り記号では機能しませんが、それ以外の場合はすべてのエンジンで機能します。
\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}

余談: これは特に高速ではありません。etlリストの各要素のスペースとグループをチェックする必要があるため、@StevenB.Segletes によるソリューションよりもバックグラウンドで多くの処理が行われます。これは、スペースをカウントしたり、グループに再帰したりする必要がある場合にのみ必要です。

関連情報