Ordenar para que coincida con una lista determinada

Ordenar para que coincida con una lista determinada

Estoy buscando ideas sobre la siguiente tarea. Quiero ordenar las entradas en \listbaquellas en \lista. No siempre se puede suponer que sólo los elementos de \listaestán en \listb; tampoco se puede suponer que todos los elementos de \listaestén en \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

Aquí quiero \listbconvertirme {a,b,c,e,h,f,g}. Nota: e,h,f,gen los resultados \listbse debe seguir su 'ordenamiento parcial' en el original \listb, es decir, cómo estaban ordenados en el original \listb.

Respuesta1

TeX simple (aunque funcionaría en LaTeX, por supuesto)

\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.

Respuesta2

En primer lugar, me disculpo por mi intento de novato.

Aquí hay una humilde idea que tuve con 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}

La salida:

mi salida

Espero que ayude de alguna manera.:)

Respuesta3

Aquí está la solución de David Carlisle. Mi única preocupación es el aumento exponencial en la cantidad de controles definidos, incluso con el recolector de basura (grupo local) que he usado.

\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

Lo he generalizado para aceptar analizadores de listas arbitrarios.

\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}

El siguiente enfoque evita definir una gran cantidad de macros temporales, pero (como el de Paulo Cereda) es más lento que el 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}

información relacionada