列表中最大元素的位置

列表中最大元素的位置

考虑以下:

\documentclass{article}

\usepackage{expl3}

\ExplSyntaxOn
  \cs_new_eq:NN \calc \fp_eval:n
\ExplSyntaxOff

\def\valueA{7}
\def\valueB{19}
\def\valueC{41}
\def\valueD{31}
\def\valueE{25}
\def\valueF{17}
\def\valueG{7}
\def\valueH{3}

\begin{document}

\noindent I have the list
\[
\valueA,\valueB,\valueC,\valueD,\valueE,\valueF,\valueG,\valueH
\]
in which the largest element is $\calc{max(\valueA,\valueB,\valueC,\valueD,\valueE,\valueF,\valueG,\valueH)}$ (but that is of no importance to me).\\[\baselineskip]
How can I get \LaTeX{} to extract the position number of the largest element in a list? (In the example above, the answer is of course `$3$'.)

\end{document}

输出

笔记

它不一定是 LaTeX 3 解决方案,但我需要通过latex--> dvips-->编译原始文档(即我需要解决方案的文档) ps2pdf

此外,该列表是通过该\def方法生成的。

答案1

我们可以使用一个或两个循环来expl3实现这一点。一个循环版本需要计算出最大值并同时跟踪位置:

\documentclass{article}
\usepackage{expl3,xparse}
\ExplSyntaxOn
\NewDocumentCommand \maxposition { m }
  {
    \svend_clist_pos_max:n {#1}
  }
\cs_new:Npn \svend_clist_pos_max:n #1
  {
    \__svend_clist_pos_max:nnnw \c_zero \c_zero { -\c_max_int }
      #1 , \q_recursion_tail , \q_recursion_stop
  }
 \cs_new:Npn \__svend_clist_pos_max:nnnw #1#2#3#4 ,
   {
     \quark_if_recursion_tail_stop_do:nn {#4} {#1}
     \fp_compare:nNnTF {#4} > {#3}
       {
         \__svend_clist_pos_max:fnnw 
           { \int_eval:n { #1 + #2 + \c_one } } \c_zero {#4}
       }
       {
         \__svend_clist_pos_max:nfnw 
           {#1} { \int_eval:n { #2 + \c_one } } {#3}
       }
  }
\cs_generate_variant:Nn \__svend_clist_pos_max:nnnw { f , nf }
\ExplSyntaxOff

\def\valueA{7}
\def\valueB{19}
\def\valueC{41}
\def\valueD{31}
\def\valueE{25}
\def\valueF{17}
\def\valueG{7}
\def\valueH{3}

\begin{document}

\maxposition{\valueA,\valueB,\valueC,\valueD,\valueE,\valueF,\valueG,\valueH}

\end{document}

而双循环版本首先找到最大值,然后找到位置,因此一次跟踪的东西更少

\documentclass{article}
\usepackage{expl3,xparse}
\ExplSyntaxOn
\NewDocumentCommand \maxposition { m }
  {
    \svend_clist_pos_max:n {#1}
  }
\cs_new:Npn \svend_clist_pos_max:n #1
  {
    \__svend_clist_pos_max:fn
      {
        \__svend_clist_pos_max:nw { -\c_max_int }
          #1 , \q_recursion_tail , \q_recursion_stop
      } {#1}
  }
\cs_new:Npn \__svend_clist_pos_max:nw #1#2 ,
  {
    \quark_if_recursion_tail_stop_do:nn {#2} {#1}
    \fp_compare:nNnTF {#2} > {#1}
      { \__svend_clist_pos_max:nw {#2} }
      { \__svend_clist_pos_max:nw {#1} }
  }
\cs_new:Npn \__svend_clist_pos_max:nn #1#2
  {
    \__svend_clist_pos_max:nnw { 1 } {#1}
      #2 , \q_recursion_tail , \q_recursion_stop
  }
\cs_generate_variant:Nn \__svend_clist_pos_max:nn { f }
\cs_new:Npn \__svend_clist_pos_max:nnw #1#2#3 ,
  {
    \quark_if_recursion_tail_stop_do:nn {#3} {#1}
    \int_compare:nNnT {#2} = {#3}
      { \use_i_delimit_by_q_recursion_stop:nw {#1} }
    \__svend_clist_pos_max:fnw { \int_eval:n { #1 + \c_one } } {#2}
  }
\cs_generate_variant:Nn \__svend_clist_pos_max:nnw { f }


\cs_new:Npn \__svend_list_max:nw #1#2 ,
  {
    \quark_if_recursion_tail_stop_do:nn {#2} {#1}
    \int_compare:nNnTF {#2} > {#1}
      { \__svend_list_max:nw {#2} }
      { \__svend_list_max:nw {#1} }
  }
\ExplSyntaxOff

\def\valueA{7}
\def\valueB{19}
\def\valueC{41}
\def\valueD{31}
\def\valueE{25}
\def\valueF{17}
\def\valueG{7}
\def\valueH{3}

\begin{document}

\maxposition{\valueA,\valueB,\valueC,\valueD,\valueE,\valueF,\valueG,\valueH}

\end{document}

其思路是首先使用一个映射找到最大的条目,然后使用第二个映射找到该条目的位置。一切都可以在代码级别扩展,因此您可以\DeclareExpandableDocumentCommand根据需要在这里使用。

答案2

这是一个etoolbox

在此处输入图片描述

\documentclass{article}

\usepackage{expl3,etoolbox}

\ExplSyntaxOn
  \cs_new_eq:NN \calc \fp_eval:n
\ExplSyntaxOff

\def\valueA{7}
\def\valueB{19}
\def\valueC{41}
\def\valueD{31}
\def\valueE{25}
\def\valueF{17}
\def\valueG{7}
\def\valueH{3}

\makeatletter
\newcounter{maxindex}
\newcommand{\findmaxindex}[1]{%
  \@tempcnta=0% Counter for stepping through elements
  \setlength{\@tempdima}{-\maxdimen}% "Smallest" number as a length/dimension
  \renewcommand*{\do}[1]{%
    \advance\@tempcnta by 1% Step to next element
    \ifdimgreater{##1pt}{\@tempdima}{\setlength{\@tempdima}{##1pt}\setcounter{maxindex}{\@tempcnta}}{}}% Found larger element
  \docsvlist{#1}% process list to find maximum number and index
}
\makeatother

\setlength{\parindent}{0pt}% Just for this example
\begin{document}

I have the list
\[
  7, 19, 41, 31, 25, 17, 7, 3
\]
in which the largest element is $\calc{max(7, 19, 41, 31, 25, 17, 7, 3)}$.

\findmaxindex{7, 19, 41, 31, 25, 17, 7, 3}% Find maximum number index
The position number of the largest element in this \themaxindex.

\bigskip

I have the list
\[
  \valueH,\valueG,\valueF,\valueE,\valueD,\valueC,\valueB,\valueA
\]
in which the largest element is $\calc{max(\valueH,\valueG,\valueF,\valueE,\valueD,\valueC,\valueB,\valueA)}$.

\findmaxindex{\valueH,\valueG,\valueF,\valueE,\valueD,\valueC,\valueB,\valueA}% Find maximum number index
The position number of the largest element in this \themaxindex.

\end{document}

请注意,它将选择作为索引第一的最大的元素。最大数字的索引存储在计数器中maxindex,可通过打印\themaxindent

其思路是遍历列表并标记每个被发现大于前一个最大元素的元素。使用维度允许处理十进制数。

答案3

另一个可扩展的解决方案。没有使用任何包。(对于这种情况,仅处理整数,对于小数,可以\ifnum\ifdim一定程度上用 替换;对于更复杂的情况,其中包括xint)。

\documentclass{article}

\def\valueA{7}
\def\valueB{19}
\def\valueC{41}
\def\valueD{31}
\def\valueE{25}
\def\valueF{17}
\def\valueG{7}
\def\valueH{3}

\def\mylist{\valueA,\valueB,\valueC,\valueD,\valueE,\valueF,\valueG,\valueH}

\makeatletter
% the two routines \maxoflist and \maxposition are not optimal if the
% list elements require some costly expansion to compute their values
% this could be improved, if needed, to do this expansion only once
% I here design the thing for either litteral digit tokens or 
% \count registers or the like

% naturally one could also do a single routine with a two element
% output: (earliest) position and value of the maximum

% maximum
\def\maxoflist #1{\romannumeral0\expandafter
                    \maxoflist@a\romannumeral-`0#1,,}
\def\maxoflist@a #1,{\maxoflist@c {\numexpr#1\relax}}
\def\maxoflist@c #1#2,{%
    \ifx\relax #2\relax\expandafter\maxoflist@end
    \else\ifnum#2>#1\expandafter\expandafter\expandafter\maxoflist@update
               \else\expandafter\expandafter\expandafter\maxoflist@next
    \fi\fi {#1}{#2}}
\def\maxoflist@end    #1#2{\expandafter\space\the#1}
\def\maxoflist@update #1#2{\maxoflist@c {\numexpr#2\relax}}
\def\maxoflist@next   #1#2{\maxoflist@c {#1}}

% max position
\def\maxposition #1{\romannumeral0\expandafter
                    \maxposition@a\romannumeral-`0#1,,}
\def\maxposition@a #1,{\maxposition@c 21{\numexpr#1\relax}}
\def\maxposition@b #1%
   {\expandafter\maxposition@c\expandafter {\the\numexpr #1+\@ne}}%
\def\maxposition@c #1#2#3#4,{%
    \ifx\relax #4\relax\expandafter\maxposition@end
    \else\ifnum#4>#3\expandafter\expandafter\expandafter\maxposition@update
               \else\expandafter\expandafter\expandafter\maxposition@next
    \fi\fi {#1}{#2}{#3}{#4}}
\def\maxposition@end #1#2#3#4{ #2}
\def\maxposition@update #1#2#3#4{\maxposition@b {#1}{#1}{\numexpr#4\relax}}
\def\maxposition@next   #1#2#3#4{\maxposition@b {#1}{#2}{#3}}
\makeatother


\begin{document}

\noindent I have the list
\[
\mylist
\]
in which the largest element is $\maxoflist\mylist$ (but that is 
of no importance to me).\\[\baselineskip]
How can I get \LaTeX{} to extracting the position number 
of the largest element in a list? (In the example above, 
the answer is of course `$\maxposition\mylist$'.)

\end{document}

最大位置

答案4

pgfmath

在此处输入图片描述

\documentclass[a4paper]{article}
\usepackage{tikz}
\begin{document}
\def\mylist{7, 19, 41, 31, 25, 17, 7, 3}
\pgfmathtruncatemacro\Max{max(\mylist)}

\foreach[count=\Pos] \k in \mylist {
\pgfmathsetmacro\test{\k==\Max ?  \Pos :  0}
\ifnum\test=0 \else \xdef\MaxPos{\test} \fi
}

In \{\mylist\} the maximum is  {\Max} at list-position \MaxPos.
\end{document}

相关内容