如何从列表中选择一个字符(或单词)

如何从列表中选择一个字符(或单词)

有没有办法,但有以下限制:

  • 无外部包(即无substr
  • 无条件(\ifnum\ifdefined等)

从字符串中选择一个字符?即

\CharAt{2}{ABC}   

应该得到 B。或者至少是来自分隔参数的一个单词?即

\WordAt{2}{A B C} 

应该产生 B。

数组的大小是固定的,因此下面的方法也可以起作用:

\WordAt{2}{A}{B}{C}

重点是使 LaTeX 简单,因为我正在使用plastex

答案1

如果位置编号为 9 或更少,则以下操作有效:

\documentclass{article}
\def\ninthofmany#1#2#3#4#5#6#7#8#9{#9\gobbletorelax}
\def\gobbletorelax#1\relax{}
\def\CharAt#1#2{%
  \expandafter\ninthofmany\romannumeral\numexpr(9000-\number#1000)#2\relax}
\begin{document}
\CharAt{3}{abcdefg}
\CharAt{2}{abcdefg}
\CharAt{1}{abcdefg}
\end{document}

\CharAt{3}{abcdefg}例如,在字符串前面添加 6 个“m”(罗马数字 6000)abcdefg,然后取出结果中的第 9 个字符。使用相同技巧的迭代,可以根据需要扩展第一个参数的限制,但代价是代码越来越长。

如果我们不需要避免\ifnum(以及大概其他\if),那么我们可以用几行代码轻松地解决任意大数的这个难题。

答案2

它只能在搜索字符串的前 8 个字符时才有效,如果字符串只有 9 个字符长,它可以获取第 9 个字符。字符串参数中的空格会被忽略。它还可以解析单词列表,其中第一个参数指定为 {{word1}{word2}{word3}...}

\documentclass{article}
\def\nextchar#1#2#3#4#5#6#7#8#9\relax{%
  \def\1{#1}%
  \def\2{#2}%
  \def\3{#3}%
  \def\4{#4}%
  \def\5{#5}%
  \def\6{#6}%
  \def\7{#7}%
  \def\8{#8}%
  \def\9{#9}%
}
\newcommand\findchar[2]{%
  \nextchar#1\relax\relax\relax\relax\relax\relax\relax\relax\relax%
  \csname#2\endcsname%
}
\begin{document}
\findchar{abc}{2}
should give a b

\findchar{thisisatest}{7}
gives the same result as
\findchar{this is a test}{7}

\findchar{123456789}{9}
can find the ninth character, since the string is only 9 in length

\findchar{{This}{is}{a}{test}{of}{the}{emergency}{broadcast}{system}}{7}
can be found among word lists too.
\end{document}

在此处输入图片描述

答案3

我查看了一些plastexpdf 文档,但找不到关于什么是可以接受的和什么是不可接受的具体解释。

作为一种修辞练习,这里有一个宏\NthElt {N}{list},它返回(可扩展地)列表的第 N 个元素(空格吞噬),该列表可能是扩展为某个字符串的宏,或者是其他一些带括号的东西的列表;必须N是一个明确的正整数。

我的限制是不使用任何\if,但由于它已在其他答案中使用,我允许自己使用分隔宏和\romannumeral。 可以完全删除的使用\romannumeral;分隔宏是该方法的核心。

e-TeX正是\numexpr至关重要的用法。

\documentclass{article}

\makeatletter
\def\gobble@     {}%
\def\gobble@i    #1{}%
\def\gobble@ii   #1#2{}%
\def\gobble@iii  #1#2#3{}%
\def\gobble@iv   #1#2#3#4{}%
\def\gobble@v    #1#2#3#4#5{}%
\def\gobble@vi   #1#2#3#4#5#6{}%
\def\gobble@vii  #1#2#3#4#5#6#7{}%

\def\gobtoundef    #1\undef {}% 
\def\gobtonine     #19{}%
%\def\FirstOfTwo   #1#2{#1}%   here, LaTeX: just use \@firstoftwo
%\def\ThirdOfThree #1#2#3{#3}% here, LaTeX: just use \@thirdofthree

% EXPANDABLY RECOVERS THE #1th ITEM
% #1 MUST BE AN EXPLICIT POSITIVE INTEGER  (not a count or not even a macro)
%     
\def\NthElt #1#2%
{%
    \romannumeral0\expandafter\NthElta\expandafter {\romannumeral-`0#2}{#1}%
}%
\def\NthElta #1#2%
{%
    \NthEltb {#2}#1\undef\undef\undef\undef\undef\undef\undef\undef\UNDEF
}%
\def\NthEltb #1%
{%
    \IfMoreThanEight #1\undef\@firstoftwo {\NthEltc}{\NthEltGetIt}%
    {#1}%
}%
\def\IfMoreThanEight #1#2%
{% 
    \gobtoundef #2\PerhapsAtMostEight #1%
}%
\def\PerhapsAtMostEight #1%
{%
    \gobtonine #1\gobble@ii 9\@thirdofthree
}%
\def\NthEltc #1#2#3#4#5#6#7#8#9%
{%
    \gobtoundef #9\NthEltSilentEnd\undef
    \expandafter\NthEltb\expandafter{\the\numexpr #1-8\relax}%
}%
\def\NthEltSilentEnd #1\UNDEF { }%  space stops the \romannumeral0
\def\NthEltGetIt #1%
{%
    \expandafter\expandafter\expandafter\NthEltFinish
    \csname gobble@\romannumeral\numexpr#1-1\endcsname
}%
\def\NthEltFinish #1#2\UNDEF  {\gobtoundef #1\expandafter\space
                                             \gobble@iii\undef\space #1}% 
% space stops the \romannumeral0
\makeatother

\begin{document}    
\NthElt {1}{ABCDEFGHIJKLMNOPQRSTUVWXYZ}

\NthElt {7}{ABCDEFGHIJKLMNOPQRSTUVWXYZ}

\NthElt {26}{ABCDEFGHIJKLMNOPQRSTUVWXYZ}

+++\NthElt {27}{ABCDEFGHIJKLMNOPQRSTUVWXYZ}+++

% 0 is not legal as index, but acts as if 1.
+++\NthElt {0}{ABCDEFGHIJKLMNOPQRSTUVWXYZ}+++

\newcount\cnta
\loop
   \advance\cnta 1
      \expandafter\NthElt\expandafter{\the\cnta}{ABCDEFGHIJKLMNOPQRSTUVWXYZ}.%
   \ifnum\cnta < 30
\repeat

\edef\z {\NthElt
  {37}{ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJ{THIS IS ME!}LMNOPQRSTUVWXYZ}}
\texttt{\meaning\z}

\end{document}

第 n 个元素

相关内容