Emparejar elementos de dos listas separadas por comas en una sola lista

Emparejar elementos de dos listas separadas por comas en una sola lista

¿Cómo emparejar elementos de dos listas separadas por comas (suponiendo que tengan la misma longitud) en otra lista?

Hice lo mejor que pude para buscar la respuesta antes de preguntar... ¡así que espero que esto no sea un duplicado!

Por ejemplo, dado a las listas \def\a{1,2,3,4,5} y \def\b{a,b,c,d,e} quiero definir \parlistslas que \def\c{\pairlists[=]{\a}{\b}} definirán \c as {1=a,2=b,3=c,4=d,5=e}.

No soy ningún experto en TeX, pero aun así tuve un éxito parcial: funciona cuando las listas se dan como parámetros, pero no cuando las listas se almacenan en los comandos \ay \b. Vea mi intento a continuación... Cualquier ayuda será muy apreciada. Gracias.

\documentclass{minimal}

\usepackage{xifthen}

\makeatletter
\def\@pairitems[#1]#2,#3\@nil#4,#5\@nil{%
% [#1][#2,#3][#4,#5]%
  \ifthenelse{\equal{#3}{}}{%
    \ifthenelse{\equal{#5}{}}%
      {#2#1#4}%
      {\PackageError{example}{Lists are not the same size}}%
  }{%
    \ifthenelse{\equal{#5}{}}%
      {\PackageError{example}{Lists are not the same size}}%
      {#2#1#4, \@pairitems[#1]#3\@nil#5\@nil}%
  }%
}
\def\pairitems[#1]#2#3{\@pairitems[#1]#2,\@nil#3,\@nil}
\makeatother


\begin{document}

\def\a{1,2,3,4,5}
\def\b{a,b,c,d,e}
\def\x{\pairitems[=]{1,2,3,4,5}{a,b,c,d,e}}
\def\y{\pairitems[=]{\a}{\b}}

\noindent
x: \x\\
y: \y\\

\end{document}

ingrese la descripción de la imagen aquí

Respuesta1

Esta es una solución que utiliza el enfoque LaTeX3. Vale la pena señalar que LaTeX es un lenguaje de macros. Puede utilizar \meaningpara mostrar la definición de un comando. Cuando defines \def\x{\pairitems{\a}{\b}}, entonces \xes \pairitems{\a}{\b}, literalmente, el valor de \pairitems{\a}{\b}. Si desea \xcontener el valor de \pairitems{\a}{\b}, es necesario realizar algún tratamiento especial.

\documentclass{minimal}
\usepackage[T1]{fontenc}
\usepackage{expl3}
\usepackage{xparse}


\ExplSyntaxOn

\clist_new:N \l_doc_tmpa_clist
\clist_new:N \l_doc_tmpb_clist
\seq_new:N \l_doc_tmpa_seq

\msg_new:nnn {doc} {difflen} {two~comma~separated~lists~have~different~length}


\cs_set:Npn \doc_pair_items:nnn #1#2#3 {
    \clist_set:Nn \l_doc_tmpa_clist {#2}
    \clist_set:Nn \l_doc_tmpb_clist {#3}
    \seq_clear:N \l_doc_tmpa_seq
    
    \int_compare:nNnF {\clist_count:N \l_doc_tmpa_clist} = {\clist_count:N \l_doc_tmpb_clist} {
        \msg_error:nn {doc} {difflen}
    }
    
    \int_step_inline:nn {\clist_count:N \l_doc_tmpa_clist} {
        \seq_put_right:Nn \l_doc_tmpa_seq {
            \clist_item:Nn \l_doc_tmpa_clist {##1}
            #1
            \clist_item:Nn \l_doc_tmpa_clist {##1}
        }
    }
    
    \seq_use:Nn \l_doc_tmpa_seq {,}
}

\cs_generate_variant:Nn \doc_pair_items:nnn {nxx}
\cs_generate_variant:Nn \doc_pair_items:nnn {noo}

\newcommand{\pairitems}[3][=]{
    \doc_pair_items:nnn {#1} {#2} {#3}
}

\newcommand{\pairitemso}[3][=]{
    \doc_pair_items:noo {#1} {#2} {#3}
}

\newcommand{\pairitemsx}[3][=]{
    \doc_pair_items:nxx {#1} {#2} {#3}
}

\ExplSyntaxOff


\begin{document}

\par\pairitems{1,2,3,4,5}{a,b,c,d,e}
\par\pairitems[+]{1,2,3,4,5}{a,b,c,d,e}

\def\a{1,2,3,4,5}
\def\b{a,b,c,d,e}
\par\pairitems{\a}{\b}
\par\pairitemso{\a}{\b}

\def\x{\pairitemso{\a}{\b}}
\par\meaning\x
\edef\x{\noexpand\pairitemso{\a}{\b}}
\par\meaning\x

\end{document}

Respuesta2

Esto produce una salida terminal.

> \zc=macro:
->1=a, 2=b, 3=c, 4=d, 5=e.

y componer

ingrese la descripción de la imagen aquí

Tenga en cuenta el uso de \unexpandedpara que los términos de la lista estén protegidos contra la expansión, aunque se utilice edef para guardar el resultado. Cambié el orden de llamada haciendo que el comando defina el token especificado\zc

\documentclass{article}

% don't break latex accent support by redefining \a \b or \c which are
% all core latex commands....

\def\za{1,2,3,4,5}
\def\zb{a,b,c,d,e}

\newcommand\pairlists[4][=]{%
 \edef#2{%
 \expandafter\expandafter\expandafter\xpairlists
 \expandafter#3\expandafter,\expandafter\relax#4,\relax#1\zstop
 }}

\def\xpairlists#1,#2\relax#3,#4\relax#5\zstop{%
   \unexpanded{#1#5#3}%
   \ifcat$\detokenize{#2}$%
     \expandafter\gobblezstop
   \fi
   , \xpairlists#2\relax#4\relax#5\zstop}

\def\gobblezstop#1\zstop{}

\pairlists[=]{\zc}{\za}{\zb}

\show\zc

\begin{document}
\zc
\end{document}

Respuesta3

Necesita hacer algunos \expandaftertrucos de intercambio de argumentos para que las macros que contienen las listas de elementos separados por comas se expandan antes de \pairitemsllevarse a cabo.

En caso de que no le guste usar \edef(lo que también desencadenaría la expansión de los elementos separados por comas de la lista de comas), puede (¿ab?)usar \romannumerallo que desencadena la expansión hasta que haya reunido un archivo TeX válido.⟨número⟩-cantidad y en caso de que TeX-⟨número⟩-cantidad denota un valor no positivo, simplemente devora silenciosamente los tokens que forman ese TeX-⟨número⟩-cantidad.

\documentclass[a4paper, landscape]{article}

%===================[adjust margins/layout for the example]====================
\csname @ifundefined\endcsname{pagewidth}{}{\pagewidth=\paperwidth}%
\csname @ifundefined\endcsname{pdfpagewidth}{}{\pdfpagewidth=\paperwidth}%
\csname @ifundefined\endcsname{pageheight}{}{\pageheight=\paperheight}%
\csname @ifundefined\endcsname{pdfpageheight}{}{\pdfpageheight=\paperheight}%
\textwidth=\paperwidth
\oddsidemargin=1.5cm
\marginparsep=.2\oddsidemargin
\marginparwidth=\oddsidemargin
\advance\marginparwidth-2\marginparsep
\advance\textwidth-2\oddsidemargin
\advance\oddsidemargin-1in
\evensidemargin=\oddsidemargin
\textheight=\paperheight
\topmargin=1.5cm
\footskip=.5\topmargin
{\normalfont\global\advance\footskip.5\ht\strutbox}%
\advance\textheight-2\topmargin
\advance\topmargin-1in
\headheight=0ex
\headsep=0ex
\pagestyle{plain}
\parindent=0ex
\parskip=0ex 
\topsep=0ex
\partopsep=0ex
%==================[eof margin-adjustments]====================================

\makeatletter
\newcommand\Exchange[2]{#2#1}%
\newcommand\CheckWhetherNull[1]{%
  \ifcat Y\detokenize{#1}Y%
  \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
}%
\@ifdefinable\@pairitems{%
  \long\def\@pairitems#1#2,#3\@nil#4,#5\@nil#6{%
    \CheckWhetherNull{#3}{%
      \CheckWhetherNull{#5}%
        {\z@#6#2#1#4}%
        {\z@\PackageError{example}{Lists are not the same size}}%
    }{%
      \CheckWhetherNull{#5}%
        {\z@\PackageError{example}{Lists are not the same size}}%
        {\@pairitems{#1}#3\@nil#5\@nil{#6#2#1#4,}}%
    }%
  }%
}%
\newcommand\pairitems[3]{\romannumeral\@pairitems{#1}#2,\@nil#3,\@nil{}}
\makeatother


\begin{document}

\newcommand*\one{1}
\newcommand*\two{2}
\newcommand*\three{3}
\newcommand*\four{4}
\newcommand*\five{5}
\newcommand*\MYa{a}
\newcommand*\MYb{b}
\newcommand*\MYc{c}
\newcommand*\MYd{d}
\newcommand*\MYe{e}

\newcommand*\ListA{\one,\two,\three,\four,\five}
\newcommand*\ListB{\MYa,\MYb,\MYc,\MYd,\MYe}
\newcommand*\PairedU{\pairitems{=}{\one,\two,\three,\four,\five}{\MYa,\MYb,\MYc,\MYd,\MYe}}
\newcommand*\PairedV{\expandafter\Exchange\expandafter{\expandafter{\ListB}}{\expandafter\Exchange\expandafter{\expandafter{\ListA}}{\pairitems{=}}}}
\expandafter\newcommand\expandafter*\expandafter\PairedW\expandafter{%
  \romannumeral0\Exchange{ }{\expandafter\expandafter\expandafter}\pairitems{=}{\one,\two,\three,\four,\five}{\MYa,\MYb,\MYc,\MYd,\MYe}%
}
\expandafter\newcommand\expandafter*\expandafter\PairedX\expandafter{%
  \romannumeral0%
  \expandafter\Exchange\expandafter{\expandafter{\ListB}}{%
    \expandafter\Exchange\expandafter{\expandafter{\ListA}}{%
      \Exchange{ }{\expandafter\expandafter\expandafter}\pairitems{=}%
    }%
  }%
}

\csname @ifdefinable\endcsname\PairedY{%
  \edef\PairedY{\pairitems{=}{\one,\two,\three,\four,\five}{\MYa,\MYb,\MYc,\MYd,\MYe}}%
}%

\csname @ifdefinable\endcsname\PairedZ{%
  \edef\PairedZ{\expandafter\Exchange\expandafter{\expandafter{\ListB}}{\expandafter\Exchange\expandafter{\expandafter{\ListA}}{\pairitems{=}}}}%
}%

\noindent{\ttfamily \string\PairedU:\\\meaning\PairedU}\\$\to$\PairedU\bigskip

\noindent{\ttfamily \string\PairedV:\\\meaning\PairedV}\\$\to$\PairedV\bigskip

\noindent{\ttfamily \string\PairedW:\\\meaning\PairedW}\\$\to$\PairedW\bigskip

\noindent{\ttfamily \string\PairedX:\\\meaning\PairedX}\\$\to$\PairedX\bigskip

\noindent{\ttfamily \string\PairedY:\\\meaning\PairedY}\\$\to$\PairedY\bigskip

\noindent{\ttfamily \string\PairedZ:\\\meaning\PairedZ}\\$\to$\PairedZ

\end{document}

ingrese la descripción de la imagen aquí

Por supuesto, todo esto sin tener en cuenta el caso de dos listas vacías.
Además, no se tratan los tokens de espacio que rodean los elementos de la lista separados por comas.
Además, no existe un tratamiento especial para los elementos de la lista en blanco o vacía.

Respuesta4

Hice la sintaxis un poco diferente, si eso funciona para el OP. Aquí, se ejecuta \makepairlist[=]{\a}{\b}para crear la lista de pares deseada en una macro \thepairlist. En el MWE, muestro que la macro detokenizada ya está expandida a la lista deseada.

Si se desea, se puede continuar con \edef\c{\thepairlist}o, mejor aún, \let\c\thepairlist.

\documentclass{article}
\usepackage{listofitems}
\newcommand\makepairlist[3][:]{%
  \readlist\ListA{#2}%
  \readlist\ListB{#3}%
  \def\thepairlist{}%
  \foreachitem\z\in\ListA[]{%
    \ifnum\zcnt=1\relax\else\edef\thepairlist{\thepairlist,}\fi
    \edef\thepairlist{\thepairlist\z#1\ListB[\zcnt]}%
  }%
}
\begin{document}
\def\a{1,2,3,4,5}
\def\b{a,b,c,d,e}
\makepairlist[=]{\a}{\b}
\thepairlist

\detokenize\expandafter{\thepairlist}
\end{document}

ingrese la descripción de la imagen aquí

información relacionada