如何计算 token 列表中 token 的频率

如何计算 token 列表中 token 的频率

是否有可能计算令牌列表中令牌的数量?

\documentclass{article}

\usepackage{expl3}

\ExplSyntaxOn

\tl_new:N \tobi_list_tl
\tl_set:Nn \tobi_list_tl {foo~bar~baz}

\begin{document}
'\tl_use:N \tobi_list_tl'~contains~?~spaces.
\end{document}

在排版音节和韵律符号的宏中,我需要计算标记列表中的空格数。

\cs_new_protected:Npn \tobi_metrics:nn #1 #2
 {
  \tl_set:Nn \l_tobi_words_tl { #2 }
  % change spaces into -\q_tobi_space_marker-
  \tl_replace_all:Nnn \l_tobi_words_tl { ~ } { - \q_tobi_space_marker - }
  % split the (modified) second argument at -
  \seq_set_split:NnV \l_tobi_syllables_seq { - } \l_tobi_words_tl
  % split the first argument "at nothing"
  \seq_set_split:Nnn \l_tobi_measures_seq { } { #1 }
  % AT THIS POINT I WANT TO KNOW THE NUMBER OF SPACES                          <---------
  % IN \l_tobi_words OR THE NUMBER OF \q_tobi_space_marker                  <------------
  % IN \l_tobi_syllables_seq                                                   <---------
  \int_zero:N \l_tobi_process_int
  \seq_map_inline:Nn \l_tobi_syllables_seq
   {
    \int_incr:N \l_tobi_process_int
    \tl_if_eq:nnTF { ##1 } { \q_tobi_space_marker }
     {% we had a space, step back the counter and issue a space
      \int_add:Nn \l_tobi_process_int { -1 }
      \c_space_token
     }
     {% print the syllable with the metric marker
      \tobi_print_syllable:n { ##1 }
     }
   }
 }

https://tex.stackexchange.com/a/124531/4918

我需要数字来检查列表中是否有足够的符号可以与音节结合,这是我迄今为止的测试:

\int_compare:nT
 {
  \seq_count:N \l_@@_syllables_seq - 1 != \seq_count:N \l_@@_symbols_seq
 }
 {
  ERROR
 }

必须-1用空格数替换。


也许我应该添加一些关于用法的信息。这将是宏的一部分

   \metrics{_    u  u  _   _  _  | _    _  u  u   _  _   _   }
           {flos ve-te-ris vi-ni | meis na-ri-bus ob-iec-tust}

第一个参数是一个空格分隔的度量符号列表(通过缩写访问,如u_),第二个列表包含带连字符的单词。我需要检查每个音节是否有一个符号,但\seq_count:在这里不起作用,因为第二个列表中的空格被特殊处理。测试必须是

# of symbols         = # of syllables
lengt of symbol list = lengthh of syllablelist – # of spaces 

这是完整处理宏的最新版本:

\cs_new_protected:Npn \__metrix_metrics:nn #1 #2
 {
  \tl_set:Nn \l__metrix_words_tl { #2 }
  \tl_replace_all:Nnn \l__metrix_words_tl { ~ } { - \q__metrix_space_marker - }
  \seq_set_split:NnV \l__metrix_syllables_seq { - } \l__metrix_words_tl
  \seq_set_split:Nnn \l__metrix_symbols_seq { ~ } { #1 }
  \int_zero:N \l__metrix_process_int
  \seq_map_inline:Nn \l__metrix_syllables_seq
   {
    \tl_if_eq:nnT { ##1 } { \q__metrix_space_marker }
     { \int_incr:N \l__metrix_process_int }
   }
  \int_compare:nTF
   {
    \seq_count:N \l__metrix_syllables_seq -
      \seq_count:N \l__metrix_symbols_seq = \l__metrix_process_int
   }
   {
    \int_zero:N \l__metrix_process_int
    \seq_map_inline:Nn \l__metrix_syllables_seq
     {
      \int_incr:N \l__metrix_process_int
      \tl_if_eq:nnTF { ##1 } { \q__metrix_space_marker }
       {
        \int_add:Nn \l__metrix_process_int { -1 }
        \c_space_token
       }
       {
        \str_case:nnn { ##1 }
         {
          { |  } { \__metrix_l_break:  }
          { || } { \__metrix_ll_break: }
         }
         {
          \__metrix_print_syllable:n { ##1 }
         }
       }
     }
   }
   {
    \__metrix_error_msg:n { Numbers~of~symbols~and~syllables~mismatch. }
   }
 }

除了当一个或两个列表以空格结尾时,每个方法都可以工作,因此如果可以在开始处理列表之前从右侧剪切所有空格,那就太好了。

答案1

您可以通过多种方式来实现。

第一种方法(映射音节序列)

%%% Code to add for checking the syllables and the measures are the same number
\int_zero:N \l_tobi_process_int
\seq_map_inline:Nn \l_tobi_syllables_seq
 {
  \tl_if_eq:nnT { ##1 } { \q_tobi_space_marker }
   { \int_incr:N \l_tobi_process_int }
 }
\int_compare:nF
 {
  \seq_count:N \l_tobi_syllables_seq -
    \seq_count:N \l_tobi_measures_seq = \l_tobi_process_int
 }
 { ERROR! }
%%% End of code to add

第二种方式(直接计数)

这需要l3regex

\RequirePackage{l3regex}
\cs_generate_variant:Nn \regex_count:nnN { nV }

%%% Code to add for checking the syllables and the measures are the same number
\regex_count:nVN { \c{q_tobi_space_marker} } \l_tobi_words_tl \l_tobi_process_int
\int_compare:nF
 {
  \seq_count:N \l_tobi_syllables_seq -
    \seq_count:N \l_tobi_measures_seq = \l_tobi_process_int
 }
 { ERROR! }
%%% End of code to add

答案2

也许最简单的解决方案是使用标准 TeX 分隔参数方法。由于我们用空格分隔,因此这比平常稍微棘手一些:

\documentclass{article}

\usepackage{expl3}

\ExplSyntaxOn

\tl_new:N \tobi_list_tl
\tl_set:Nn \tobi_list_tl {foo~bar~baz}
\use:x
  {
    \cs_new:Npn \exp_not:N \tl_count_spaces:n ##1
      {
        \exp_not:N \int_eval:n 
          { 
            -1 \exp_not:N \__tl_count_spaces:w ##1 ~
              \exp_not:N \q_recursion_tail \c_space_tl 
              \exp_not:N \q_recursion_stop
          }
      }
  }
\cs_new:Npn \__tl_count_spaces:w #1 ~
  {
    \quark_if_recursion_tail_stop:n {#1}
    +1
    \__tl_count_spaces:w
  }
\cs_generate_variant:Nn \tl_count_spaces:n { V }
\begin{document}
'\tl_use:N \tobi_list_tl'~contains~\tl_count_spaces:V \tobi_list_tl \c_space_tlspaces.
\end{document}

您可以使用两部分方法,用于\seq_set_split:Nnn存储在空格上分割的令牌列表,然后\seq_count:N获取值。

相关内容