3

Within a self-defined macro, with which a table with the numbers of the letters of a text can be spent, I defined still another command. I have significantly reduced the macro so that only the important entries to which my question relates are present.

Because of the grouping and the need for expansion, I chose a \xdef.

\xdef\LetterQa{\seq_item:Nn\l_th_letter_qty_out_seq{1}}

I suspect that's not the correct syntax for L3.

My question is: How can I define a command in such a way that one can also pass an argument, that is, the principle (which does not work):

\xdef\LetterQ##1{\seq_item:Nn\l_th_letter_qty_out_seq{##1}}

To get a output for each possible letter, without defining for each letter an extra command.

Thanks in advance.

enter image description here

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[ngerman]{babel}
\usepackage{siunitx,xfp,xintexpr}

\ExplSyntaxOn

   \int_new:N \l_thomas_Text_ABCabc_int
   \seq_new:N \l_th_letter_All_seq
   \seq_new:N \l_th_letter_qty_out_seq
   \seq_new:N \l_th_letter_rel_qty_out_seq

   \cs_generate_variant:Nn \regex_count:nnN { xnc }

\NewDocumentCommand{ \CountLetter }{ m }
{
  \group_begin:
  \regex_count:nnN { [A-Za-z]|ü|Ü|ä|Ä|ö|Ö|ß } { #1 } \l_thomas_Text_ABCabc_int

  \seq_set_from_clist:Nn \l_th_letter_All_seq { a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,ä,ö,ü,ß }
  \seq_clear:N \l_th_letter_qty_out_seq
  \seq_clear:N \l_th_letter_rel_qty_out_seq
  \seq_map_inline:Nn \l_th_letter_All_seq
    {
     \int_zero_new:c { l_thomas_txt_ \tl_to_str:n {##1} _int }
     \regex_count:xnc { \tl_lower_case:n {##1} | \tl_upper_case:n {##1} }
                        { #1 } { l_thomas_txt_ \tl_to_str:n {##1} _int }
     \seq_put_right:Nx \l_th_letter_qty_out_seq
             { \fp_eval:n { \use:c{ l_thomas_txt_ \tl_to_str:n {##1} _int } } }
     \seq_put_right:Nx \l_th_letter_rel_qty_out_seq
             { \fp_eval:n { \use:c { l_thomas_txt_ \tl_to_str:n {##1} _int } / \l_thomas_Text_ABCabc_int } }
    }

  \xdef\LetterAll{ \fp_eval:n { \l_thomas_Text_ABCabc_int } }

  \xdef\LetterQa{ \seq_item:Nn \l_th_letter_qty_out_seq{1} }

\group_end:
}

\ExplSyntaxOff

\parindent0pt

\begin{document}

\CountLetter{Das ist ein ziemlich sinnloser Text ohne Hand und Fuß. Er lachte höhnisch, \dots }

\bigskip
In dem Text sind \LetterAll{} Buchstaben. Davon kommt das a \LetterQa{}-mal vor.

\end{document}
5
  • You are not doing what you think you are doing \xdef\LetterQ##1 does not define \LetterQa but \LetterQ{a} at most, but in that case you don't need to expand.
    – Manuel
    Commented Dec 17, 2017 at 14:13
  • Just add the definition for each letter inside the map: \cs_set_nopar:cpx { LetterQ \tl_to_str:n { ##1 } } { \seq_item:Nn \l_th_letter_qty_out_seq { \int_from_alph:n { ##1 } } } and outside of the loop the \cs_set_nopar:Npx \LetterAll { \fp_eval:n { \l_thomas_Text_ABCabc_int } }.
    – Manuel
    Commented Dec 17, 2017 at 14:17
  • @Manuel sorry for not clearly explained, I search for \LetterQ{1} , \LetterQ{1} instead of \LetterQa or \LetterQb ... so I had not to define for each letter a command.
    – user139826
    Commented Dec 17, 2017 at 14:20
  • As I said you can define each one inside the loop. But for that case you don't need x expansion, just \NewDocumentCommand \letterQ { m } { \seq_item:Nn \l_th_letter_qty_out_seq { #1 } }.
    – Manuel
    Commented Dec 17, 2017 at 14:24
  • @Manuel I can not compile the code with your hints.
    – user139826
    Commented Dec 17, 2017 at 14:30

1 Answer 1

6

I would use a property list instead of a sequence:

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[ngerman]{babel}
\usepackage{siunitx,xfp,xintexpr}

\ExplSyntaxOn

   \int_new:N \l_thomas_Text_ABCabc_int
   \seq_new:N \l_th_letter_All_seq
   \seq_new:N \l_th_letter_qty_out_seq
   \seq_new:N \l_th_letter_rel_qty_out_seq
   \prop_new:N \l_th_letter_qty_out_prop


   \cs_generate_variant:Nn \regex_count:nnN { xnc }

\NewDocumentCommand{ \CountLetter }{ m }
{
  \group_begin:
  \regex_count:nnN { [A-Za-z]|ü|Ü|ä|Ä|ö|Ö|ß } { #1 } \l_thomas_Text_ABCabc_int

  \seq_set_from_clist:Nn \l_th_letter_All_seq { a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,ä,ö,ü,ß }
  \seq_clear:N \l_th_letter_qty_out_seq
  \seq_clear:N \l_th_letter_rel_qty_out_seq
  \seq_map_inline:Nn \l_th_letter_All_seq
    {
     \int_zero_new:c { l_thomas_txt_ \tl_to_str:n {##1} _int }
     \regex_count:xnc { \tl_lower_case:n {##1} | \tl_upper_case:n {##1} }
                        { #1 } { l_thomas_txt_ \tl_to_str:n {##1} _int }
     \seq_put_right:Nx \l_th_letter_qty_out_seq
             { \fp_eval:n { \use:c{ l_thomas_txt_ \tl_to_str:n {##1} _int } } }
     \seq_put_right:Nx \l_th_letter_rel_qty_out_seq
           {\fp_eval:n { \use:c { l_thomas_txt_ \tl_to_str:n {##1} _int } / \l_thomas_Text_ABCabc_int } }  
     \prop_gput:Nnx  \l_th_letter_qty_out_prop 
      { ##1 }
      { 
       { \fp_eval:n { \use:c{ l_thomas_txt_ \tl_to_str:n {##1} _int } } }
      }
    }
     \prop_gput:Nnx  \l_th_letter_qty_out_prop {All}
     {\fp_eval:n { \l_thomas_Text_ABCabc_int}}
  \group_end:
}

\NewDocumentCommand{ \ShowCountLetter }{ m }
{ \prop_item:Nn\l_th_letter_qty_out_prop { #1 }}
\ExplSyntaxOff

\parindent0pt

\begin{document}

\CountLetter{Das ist ein ziemlich sinnloser Text ohne Hand und Fuß. Er lachte höhnisch, \dots }

\bigskip
In dem Text sind \ShowCountLetter{All} Buchstaben. Davon kommt das a \ShowCountLetter{a}-mal vor.

a: \ShowCountLetter{a}, ö: \ShowCountLetter{ö}
\end{document}

enter image description here

2
  • -@Ulrike Fischer, that is exact what I am locking for.
    – user139826
    Commented Dec 17, 2017 at 14:36
  • -@Ulrike Fischer, I would like to thank you for the great solution. It works very well. I did not know a property list yet.
    – user139826
    Commented Dec 18, 2017 at 4:12

You must log in to answer this question.