Classificando para corresponder a uma determinada lista

Classificando para corresponder a uma determinada lista

Estou procurando ideias para a seguinte tarefa. Quero classificar as entradas \listbpara aquelas em \lista. Nem sempre pode ser assumido que apenas os elementos de \listaestão dentro \listb; nem se pode presumir que todos os elementos de \listaestão em \listb.

\def\lista{a,b,c,d} % no 'e,f,g,h' in \lista
\def\listb{c,e,a,h,f,g,b} % no 'd' in \listb

Aqui, eu quero \listbme tornar {a,b,c,e,h,f,g}. Obs: e,h,f,gno resultado \listbdeverá seguir a sua 'ordenação parcial' no original \listb, ou seja, como foram ordenados no original \listb.

Responder1

plain TeX (embora funcione em LaTeX, é claro)

\def\lista{a,b,c,d}
\def\listb{c,e,a,h,f,g,b}

\def\x#1#2,{\ifx\relax#2\else
  \expandafter\let\csname #1-#2\endcsname\hbox
  \expandafter\x\expandafter#1\fi}
\def\y#1#2#3,{\ifx\relax#3\else
  \expandafter\ifx\csname #2-#3\endcsname#1,#3\fi
  \expandafter\y\expandafter#1\expandafter#2\fi}
\def\z#1,{}

\expandafter\x\expandafter a\lista,\relax,
\expandafter\x\expandafter b\listb,\relax,
\edef\listb{%
\expandafter\z\romannumeral`\x%
\expandafter\y\expandafter\hbox\expandafter b\lista,\relax,%
\expandafter\y\expandafter\relax\expandafter a\listb,\relax,}

\show\listb

\bye

This is pdfTeX, Version 3.1415926-2.4-1.40.13 (TeX Live 2012)
 restricted \write18 enabled.
entering extended mode
(./sort111.tex
> \listb=macro:
->a,b,c,e,h,f,g.
l.19 \show\listb

? 
 )
No pages of output.

Responder2

Em primeiro lugar, peço desculpas pela minha tentativa de novato.

Aqui está uma humilde ideia que tive com expl3:

\documentclass{article}

\usepackage{expl3}

\begin{document}

\def\lista{a,b,c,d}
\def\listb{c,e,a,h,f,g,b}

\ExplSyntaxOn
\clist_new:N \l_ahmed_clist
\clist_map_inline:Nn \lista
 {
  \clist_if_in:NnT \listb { #1 }
   {
    \clist_put_right:Nn \l_ahmed_clist { #1 }
   }
 }
\clist_concat:NNN \listb \l_ahmed_clist \listb
\clist_remove_duplicates:N \listb
\ExplSyntaxOff

\texttt{\meaning\listb}

\end{document}

A saída:

Minha saída

Espero que de alguma forma ajude.:)

Responder3

Aqui está a solução de David Carlisle. Minha única preocupação é o aumento exponencial no número de controles definidos, mesmo com o coletor de lixo (grupo local) que utilizei.

\def\listb{c,e,a,h,f,g,b} ->
  3601 multiletter control sequences out of 15000+200000
\def\listb{c,e,a,h,f,g,b,i,j,k} ->
  3607 multiletter control sequences out of 15000+200000

Generalizei-o para aceitar analisadores de listas arbitrárias.

\documentclass{article}
\makeatletter
% \SortToMatchGivenList[<parser>]{<master list cmd>}{<user list cmd>}
\protected\def\SortToMatchGivenList{\@testopt\S@rtToMatchGivenList,}
\def\S@rtToMatchGivenList[#1]#2#3{%
  \begingroup
  % Define temporary macros of elements of master and user lists:
  \def\x##1##2#1{%
    \ifx\relax##2\else
      \expandafter\let\csname ##1-\detokenize{##2}\endcsname\noboundary
      \expandafter\x\expandafter##1%
    \fi
  }%
  % Insert elements of master list if they appear in the user list,
  % and insert elements of user list if they don't exist in master list:
  \def\y##1##2##3#1{%
    \ifx\relax##3\else
      \expandafter\ifx\csname ##2-\detokenize{##3}\endcsname##1#1##3\fi
      \expandafter\y\expandafter##1\expandafter##2%
    \fi
  }%
  % Gobble some remnant code when building the sorted user list:
  \def\z##1#1{}%
  \expandafter\x\expandafter a#2#1\relax#1%
  \expandafter\x\expandafter b#3#1\relax#1%
  \edef#3{%
    \expandafter\z\romannumeral`\x%
    \expandafter\y\expandafter\noboundary\expandafter b#2#1\relax#1%
    \expandafter\y\expandafter\relax\expandafter a#3#1\relax#1%
  }%
  \edef\x{\endgroup\def\noexpand#3{#3}}\x
}
\makeatother

\def\lista{a,b,c,d}
\def\listb{c,e,a,h,f,g,b}
\SortToMatchGivenList\lista\listb
\show\listb

\begin{document}
x
\end{document}

A abordagem a seguir evita definir um grande número de macros temporárias, mas (como a de Paulo Cereda) é mais lenta que a de David Carlisle.

\documentclass{article}
\makeatletter
% \SortToMatchGivenList[<parser>]{<master list cmd>}{<user list cmd>}
\protected\def\SortToMatchGivenList{\@testopt\S@rtToMatchGivenList,}
\def\S@rtToMatchGivenList[#1]#2#3{%
  \begingroup
  \def\tempe##1##2{%
    \def\do####1#1{%
      \ifx\do####1\else
        \if\relax\detokenize{####1}\relax
          \let\next\do
        \else
          \edef\next{\unexpanded{##2\do}}%
        \fi
        \expandafter\next
      \fi
    }%
    \expandafter\do##1#1\do#1%
  }%
  \def\tempc##1{\unexpanded\expandafter{##1}}%
  \def\tempd##1##2{%
    \@expandtwoargs\in@
    {#1\detokenize{##1}#1}{#1\detokenize\expandafter{##2}#1}%
  }%
  \def\tempa{}\def\tempb{}%
  \tempe{#2}{%
    \tempd{##1}{#3}%
    \ifin@
      \edef\tempa{%
        \tempc\tempa\ifx\tempa\@empty\else#1\fi
        \unexpanded{##1}}%
    \fi
  }%
  \tempe{#3}{%
    \tempd{##1}\tempa
    \ifin@\else
      \edef\tempb{%
        \tempc\tempb\ifx\tempb\@empty\else#1\fi
        \unexpanded{##1}%
      }%
    \fi
  }%
  \edef\tempa{\endgroup
    \edef\noexpand#3{%
      \noexpand\unexpanded{\tempc\tempa#1\tempc\tempb}%
    }%
  }%
  \tempa
}
\makeatother

\def\lista{a,b,c,d}
\def\listb{c,e,a,h,f,g,b}
\SortToMatchGivenList\lista\listb
\show\listb

\begin{document}
x
\end{document}

informação relacionada