以可擴展的方式統計字串中特定字元出現的次數

以可擴展的方式統計字串中特定字元出現的次數

這個問題顯示如何計算字串中特定字元的出現次數。我想以一種可擴展的方式來實現,並且針對特定字元的列表(不僅僅是一個)。

\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
  • 如果指定的分隔符號之一是空格,則計數正確
  • 這不適用於非 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 的解決方案執行更多操作,只有當您確實希望能夠時才需要這樣做計算空格數,和/或遞歸分組。

相關內容