
Wie kann man Elemente aus zwei durch Kommas getrennten Listen (vorausgesetzt, sie haben die gleiche Länge) in einer anderen Liste paaren?
Ich habe mein Bestes getan, um die Antwort zu finden, bevor ich gefragt habe. Ich hoffe also wirklich, dass es sich nicht um ein Duplikat handelt!
Beispielsweise sind Listen angegeben
\def\a{1,2,3,4,5}
und
\def\b{a,b,c,d,e}
ich möchte \parlists
dies so definieren, dass
\def\c{\pairlists[=]{\a}{\b}}
definiert wird
\c as {1=a,2=b,3=c,4=d,5=e}
.
Ich bin kein TeX-Experte, aber ich hatte trotzdem einen Teilerfolg: Es funktioniert, wenn die Listen als Parameter angegeben werden, aber nicht, wenn die Listen in den Befehlen \a
und gespeichert sind \b
. Siehe meinen Versuch unten … Jede Hilfe wird sehr geschätzt. Danke.
\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}
Antwort1
Dies ist eine Lösung, die den LaTeX3-Ansatz verwendet. Es ist erwähnenswert, dass LaTeX eine Makrosprache ist. Sie können verwenden, \meaning
um die Definition eines Befehls anzuzeigen. Wenn Sie definieren \def\x{\pairitems{\a}{\b}}
, dann \x
ist \pairitems{\a}{\b}
buchstäblich anstelle des Werts von \pairitems{\a}{\b}
. Wenn Sie \x
den Wert von enthalten möchten \pairitems{\a}{\b}
, muss eine spezielle Behandlung durchgeführt werden.
\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}
Antwort2
Dies erzeugt eine Terminalausgabe
> \zc=macro:
->1=a, 2=b, 3=c, 4=d, 5=e.
und Satz
Beachten Sie die Verwendung von \unexpanded
, damit die Begriffe in der Liste vor der Erweiterung geschützt werden, auch wenn edef zum Speichern des Ergebnisses verwendet wird. Ich habe die Aufrufreihenfolge geändert, sodass der Befehl das angegebene Token definiert\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}
Antwort3
Sie müssen einige \expandafter
Tricks mit dem -und-Argumentaustausch anwenden, um die Makros, die die Listen mit durch Kommas getrennten Elementen enthalten, zu erweitern, bevor sie \pairitems
ausgeführt werden.
Falls Sie nicht verwenden möchten \edef
(was auch die Erweiterung der Komma-getrennten Elemente der Komma-Liste selbst auslösen würde), können Sie (ab?) verwenden, \romannumeral
was die Erweiterung auslöst, bis ein gültiger TeX-⟨Nummer⟩-Menge und für den Fall, dass TeX-⟨Nummer⟩-quantity bezeichnet einen nicht-positiven Wert und verschlingt stillschweigend die Token, die dieses TeX bilden.⟨Nummer⟩-Menge.
\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}
Natürlich wird dabei der Fall zweier leerer Listen nicht berücksichtigt.
Auch Leerzeichen um durch Kommas getrennte Listenelemente werden nicht behandelt.
Auch leere Listenelemente werden nicht speziell behandelt.
Antwort4
Ich habe die Syntax etwas anders gemacht, falls das für den OP funktioniert. Hier führt man aus, \makepairlist[=]{\a}{\b}
um die gewünschte Paarliste in einem Makro zu erstellen \thepairlist
. Im MWE zeige ich, dass das detokenisierte Makro bereits zur gewünschten Liste erweitert ist.
Falls gewünscht, könnte im Anschluss \edef\c{\thepairlist}
oder noch besser Folgendes hinzugefügt werden \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}