Realisierung eines Verbunds mit expl3
Mit Hilfe von expl3 will ich auf eine große Menge (ca. 5000) konstanter, gleich gearteter Objekte zugreifen, wobei jedes Objekt aus zwei Teildaten besteht. Man mag etwa an eine Menge Bücher denken, für die Buchtitel und ISBN erfasst sind, oder an Personen, von denen Name und Telefonnummer bekannt sind, oder Ähnliches.
Die natürliche Implementierung einer solchen Struktur wäre ein Verbund (auch unter den englischen Bezeichnungen record oder struct bekannt). Da expl3 so etwas anscheinend nicht direkt unterstützt, ist mein bisheriger Zugang die Realisierung der Datenstruktur mit Hilfe von zwei Komma-separierten Listen (expl-Datentyp `clist`).
Die konkrete Anforderung ist, das Vorhandensein eines Werts in der ersten Liste zu überprüfen und im positiven Fall den entsprechenden Wert aus der zweiten Liste auszugeben. Im Beispiel heißt das, dass für einen gegebenen Buchtitel überprüft werden soll, ob er erfasst ist, und dann die zugehörige ISBN ausgegeben werden soll.
Die Erstellung der Listen ist nicht das Problem, alle Daten liegen in der erforderlichen Form vor. Eine prinzipiell funktionsfähige Realisierung ist mir auch gelungen, doch ist diese sehr ineffizient, wenn der gesuchte Wert erst am Ende der Liste steht (die Kompilierung der entsprechenden Stelle dauert über 10 Sekunden).
Das Hauptproblem dabei ist meines Erachtens, dass es zwar einen Befehl gibt, mit dem das Vorkommen eines Wert Werts in einer Liste schnell überprüft werden kann (`\clist_if_in`), jedoch keine einfache Möglichkeit, die Stelle des Vorkommens (natürliche Zahl) festzustellen.
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
% geordnete Listen mit konstanten Werten:
\clist_const:Nn \c_meinmodul_erste_liste_clist {ab, cd, ef, gh, ij, kl, mn, op, qr, st}
\clist_const:Nn \c_meinmodul_zweite_liste_clist {101, 102, 103, 104, 105, 106, 107, 108, 109, 110}
\cs_new:Npn \meinmodul_suche_zweiten_wert:n #1
{
% überprüfe, ob der angegebene Wert in der ersten Liste steht:
\clist_if_in:NnTF \c_meinmodul_erste_liste_clist {#1}
{
% lege eine Kopie der zweiten Liste an:
\clist_set_eq:NN \l_tmpa_clist \c_meinmodul_zweite_liste_clist
% durchlaufe die erste Liste, der momentane Wert ist ##1:
\clist_map_inline:Nn \c_meinmodul_erste_liste_clist
{
% poppe den ersten Wert aus der Kopie der zweiten Liste und speichere ihn:
\clist_pop:NN \l_tmpa_clist \l_tmpa_tl
% überprüfe, ob der angegebene Wert der momentante Wert der ersten Liste ist:
\tl_if_eq:nnT {#1} {##1}
{
% brich die Schleife ab und gib den zuletzt gepoppten Wert zurück:
\clist_map_break:n {\l_tmpa_tl}
}
}
}
{
Wert~fehlt
}
}
\NewDocumentCommand \Wertsuche {m}
{
#1:~\meinmodul_suche_zweiten_wert:n {#1}
}
\ExplSyntaxOff
\begin{document}
\Wertsuche{ef}
\Wertsuche{st}
\Wertsuche{za}
\end{document}