
Ich möchte mehrere Datenstücke, jedes vom folgenden Typ, speichern, damit ich sie sowohl zur Formatierung als auch für Berechnungen bearbeiten kann. Die Anzahl der analysierten Zeilen im Code des Benutzers ist im Voraus nicht festgelegt.
Ich habe bereits den Parser erstellt, der diese Werte extrahiert.
LINE: 1
CTXT: xvals
LABEL: t
VAL: 1, 20, 300, 4000
LINE: 2
CTXT: imgs
LABEL: f(t)
VAL: a , b, bb, ccc, dddd
LINE: 3
CTXT: imgs
LABEL: g(t)
VAL: U, V, VV, WWW, XXXX
Ich werde in dieser einfachen Situation die folgende Ausgabe erzeugen, siehe Tabelle nicematrix
, aber das ist nur die erste Funktion. Ich möchte beispielsweise das Maximum von später im Dokument berechnen f
. Dazu muss ich den Kontext wiederherstellen, imgs
um beispielsweise das Label f(t)
und die zugehörigen Werte zu finden.
\documentclass[11pt, a4paper]{article}
\usepackage{nicematrix}
\begin{document}
\section{What the user types}
\begin{verbatim}
\begin{functable}
xvals = t : 1 , 20 , 300 , 4000 ;
imgs = f(t) : a , bb , ccc , dddd ;
g(t) : U , VV , WWW , XXXX
\end{functable}
\end{verbatim}
\section{What the user sees}
$\begin{NiceArray}[cell-space-limits = 3pt]{c*{4}{|c}}
t & 1 & 20 & 300 & 4000
\\ \hline
f(t) & a & bb & ccc & dddd
\\ \hline
g(t) & U & VV & VVV & WWW
\end{NiceArray}$
\section{What can be do after}
The user can ask for example to rebuild the 1st table
with something like this.
\begin{verbatim}
\begin{functable}[rebuild=1]
\end{functable}
\end{verbatim}
The user can also ask to calculate the maximum value
of $f(t)$ via something like \verb+\calcfunctable{max=f(t)}+.
\end{document}
Ich sehe zwei Möglichkeiten.
Entweder verwende ich das
starray
Paket, aber ich befürchte, dass dieses Projekt langfristig nicht aufrechterhalten wird.Oder ich kann versuchen, eine selbstgemachte Lösung zu implementieren, die wie eine Liste von Eigenschaftslisten aussieht.
JSON-ähnliche Struktur erwartet [2024-03-09.v1]
Die Idee besteht darin, jeder Tabelle eine Variable zuzuordnen, die Wörterbuch für Wörterbuch durchlaufen werden kann, und für jedes so erhaltene Wörterbuch haben wir Zugriff auf die unterschiedlichen Wertetypen.
[
{
'CTX' : 'xvals',
'VAL' : ['1', '20', '300', '4000'],
'LABEL': 't',
'LINE' : '1'
},
{
'CTX' : 'imgs',
'VAL' : ['a' , 'b', 'bb', 'ccc', 'dddd'],
'LABEL': 'f(t)',
'LINE' : '2'
},
{
'CTX' : 'imgs',
'VAL' : ['U', 'V', 'VV', 'WWW', 'XXXX'],
'LABEL': 'g(t)',
'LINE' : '3'
}
]
Einige zusätzliche Informationen [2024-01-17.v1]
Der Parser gibt
l3
-Token-Listen aus.Die
VAL
Schlüsselwerte können als kommagetrennte Listen oder als Sequenzen vonL3
Funktionen verwendet werden. Die zweite Möglichkeit dürfte besser sein.Die Werte werden in verschiedenen Situationen verwendet, manchmal um eine Tabelle auszudrucken, manchmal um Berechnungen durchzuführen. Dies sollte ähnlich sein wie indiese Antwort.
Proof of Concept vereinfacht [2024-03-09.v1]
\documentclass[12pt]{article}
\ExplSyntaxOn
% -- FUNCTABLE ENV. -- %
\NewDocumentEnvironment{ functable }{ b }{%
\tns_functab_functable:n { #1 }
}{}
\cs_new:Npn \tns_functab_functable:n #1 {
\tns_core_DSL_ctxt_parser:nn { functable } { #1 }
\bigskip\par
NEW ~ DATA ~ \int_use:N \g_tns_functab_id_int
\par
TODO
}
% -- DSL - L3 -- %
\tl_new:N \g_tns_functab_semicolon_tl
\tl_gset:Nn \g_tns_functab_semicolon_tl { ; }
\tl_new:N \g_tns_functab_colon_tl
\tl_gset:Nn \g_tns_functab_colon_tl { : }
\cs_generate_variant:Nn \seq_set_split:Nnn { NV }
\AtBeginDocument {
\tl_gset_rescan:NnV \g_tns_functab_semicolon_tl
{}
\g_tns_functab_semicolon_tl
\tl_gset_rescan:NnV \g_tns_functab_colon_tl
{}
\g_tns_functab_colon_tl
}
% :: AGNOSTIC PARSERS :: %
\int_new:N \g_tns_functab_id_int
\int_gset:Nn \g_tns_functab_id_int { 0 }
\int_new:N \l_tns_core_ctxt_nb_line_int
\seq_new:N \l_tns_core_ctxts_seq
\tl_new:N \l_tns_core_current_ctxt_tl
\cs_new:Npn \tns_core_DSL_ctxt_parser:nn #1#2 {
% The ID nb. of the env.
\int_gincr:N \g_tns_functab_id_int
% Line by line parsing.
%
% Lines are semi-colon separated.
\seq_set_split:NVn \l_tns_core_ctxts_seq
\g_tns_functab_semicolon_tl
{ #2 }
\int_zero:N \l_tns_core_ctxt_nb_line_int
\seq_map_inline:Nn \l_tns_core_ctxts_seq {
\bigskip\par
\int_incr:N \l_tns_core_ctxt_nb_line_int
Line ~ \int_use:N \l_tns_core_ctxt_nb_line_int
\par
% Get the context and its content.
\seq_set_split:Nnn \l_tmpa_seq { = } { ##1 }
\int_set:Nn \l_tmpa_int {\seq_count:N \l_tmpa_seq}
\quad
\int_case:nnF { \int_use:N \l_tmpa_int } {
{ 1 } {
LAST - CTXT: ~
(\tl_use:N \l_tns_core_current_ctxt_tl)
}
{ 2 } {
\seq_pop_left:NN \l_tmpa_seq \l_tns_core_current_ctxt_tl
NEW - CTXT: ~
(\tl_use:N \l_tns_core_current_ctxt_tl)
}
}{
ILLEGAL!
}
% Get the optional label and its content.
\seq_pop_left:NN \l_tmpa_seq \l_tmpa_tl
\seq_set_split:NVV \l_tmpa_seq
\g_tns_functab_colon_tl
\l_tmpa_tl
\int_set:Nn \l_tmpa_int {\seq_count:N \l_tmpa_seq}
\par\quad
\int_case:nnF { \int_use:N \l_tmpa_int } {
{ 1 } {
NO LABEL
}
{ 2 } {
\seq_pop_left:NN \l_tmpa_seq \l_tmpa_tl
LABEL: ~
$(\tl_use:N \l_tmpa_tl)$
}
}{
ILLEGAL!
}
\par\quad
\seq_pop_left:NN \l_tmpa_seq \l_tmpa_tl
VAL: ~
$(\tl_use:N \l_tmpa_tl)$
}
}
\ExplSyntaxOff
\begin{document}
\begin{functable}
xvals = t : 1 , 20 , 300 , 4000 ;
imgs = f(t) : a , bb , ccc , dddd ;
g(t) : U , VV , WWW , XXXX
\end{functable}
\end{document}
Antwort1
Aktualisieren
Der Code ist auf eine Umgebung savefunctable
und einen Befehl aufgeteilt \usefunctable
. Beide erhalten als erstes Argument einen Namen. Der Inhalt der Umgebung savefunctable
wird intern gespeichert und kann später mit dem Befehl \usefunctable
unter Angabe des entsprechenden Namens verwendet werden.
\documentclass[border=6pt,varwidth]{standalone}
\usepackage{nicematrix}
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}
\ExplSyntaxOn
\cs_generate_variant:Nn \seq_map_indexed_inline:Nn { cn }
\cs_generate_variant:Nn \seq_gset_from_clist:Nn { ce }
\seq_new:N \l__projetmbc_functable_seq
\seq_new:N \l__projetmbc_key_name_list_seq
\tl_new:N \l__projetmbc_coordinates_tl
\tl_new:N \l__projetmbc_key_tl
\tl_new:N \l__projetmbc_name_tl
\NewDocumentEnvironment { savefunctable } { m +b }
{
\seq_set_split:Nnn \l__projetmbc_functable_seq { ; } {#2}
\seq_map_inline:Nn \l__projetmbc_functable_seq
{
\seq_set_split:Nnn \l__projetmbc_key_name_list_seq { = } {##1}
\int_compare:nNnT { \seq_count:N \l__projetmbc_key_name_list_seq } = { 2 }
{
\seq_pop_left:NN \l__projetmbc_key_name_list_seq \l__projetmbc_key_tl
\seq_gclear_new:c { g__projetmbc_#1_key_\l__projetmbc_key_tl _seq }
}
\seq_set_split:Nee \l__projetmbc_key_name_list_seq { \c_colon_str } { \seq_item:Nn \l__projetmbc_key_name_list_seq { 1 } }
\seq_pop_left:NN \l__projetmbc_key_name_list_seq \l__projetmbc_name_tl
\seq_gput_right:cV { g__projetmbc_#1_key_\l__projetmbc_key_tl _seq } \l__projetmbc_name_tl
\seq_gclear_new:c { g__projetmbc_#1_key_\l__projetmbc_key_tl _name_\l__projetmbc_name_tl _seq }
\seq_gset_from_clist:ce { g__projetmbc_#1_key_\l__projetmbc_key_tl _name_\l__projetmbc_name_tl _seq } { \seq_item:Nn \l__projetmbc_key_name_list_seq { 1 } }
}
}
{}
\NewDocumentCommand \usefunctable { m m }
{
\str_case:nnF {#2}
{
{ list~of~imgs }
{
\seq_use:cn { g__projetmbc_#1_key_imgs_seq } { , ~ }
}
{ maximum~of~xvals }
{
\fp_eval:n { max ( \seq_use:cn { g__projetmbc_#1_key_xvals_name_\seq_item:cn { g__projetmbc_#1_key_xvals_seq } { 1 }_seq } { , } ) }
}
{ NiceArray }
{
$
\begin { NiceArray }
[ cell-space-limits = 3pt ]
{ c * { \seq_count:c { g__projetmbc_#1_key_xvals_name_\seq_item:cn { g__projetmbc_#1_key_xvals_seq } { 1 }_seq } } { | c } }
\seq_item:cn { g__projetmbc_#1_key_xvals_seq } { 1 } & \seq_use:cn { g__projetmbc_#1_key_xvals_name_\seq_item:cn { g__projetmbc_#1_key_xvals_seq } { 1 }_seq } { & } \\ \hline
\seq_map_indexed_inline:cn { g__projetmbc_#1_key_imgs_seq }
{
##2 & \seq_use:cn { g__projetmbc_#1_key_imgs_name_##2_seq } { & }
\int_compare:nNnF {##1} = { \seq_count:c { g__projetmbc_#1_key_imgs_seq } }
{ \\ \hline }
}
\end { NiceArray }
$
}
{ plot }
{
\tl_build_begin:N \l__projetmbc_coordinates_tl
\seq_map_indexed_inline:cn { g__projetmbc_#1_key_xvals_name_\seq_item:cn { g__projetmbc_#1_key_xvals_seq } { 1 }_seq }
{
\tl_build_put_right:Ne \l__projetmbc_coordinates_tl
{ ( ##2 , \seq_item:cn { g__projetmbc_#1_key_imgs_name_\seq_item:cn { g__projetmbc_#1_key_imgs_seq } { 1 }_seq } {##1} ) }
}
\tl_build_end:N \l__projetmbc_coordinates_tl
\begin { tikzpicture }
\begin { axis }
[
ymin = 0
]
\addplot coordinates
{ \l__projetmbc_coordinates_tl }
;
\end { axis }
\end { tikzpicture }
}
}
{ \errmessage { wrong~option~for~functable~environment } }
}
\ExplSyntaxOff
\begin{document}
\begin{savefunctable}{example 1}
xvals = t : 1 , 20 , 300 , 4000 ;
imgs = f(t) : a , bb , ccc , dddd ;
g(t) : U , VV , WWW , XXXX
\end{savefunctable}
\begin{savefunctable}{example 2}
xvals = t : 1 , 2 , 3 , 4 ;
imgs = f(t) : 8 , 5 , 7 , 6 ;
\end{savefunctable}
Using \texttt{example 1} with \texttt{NiceArray}: \usefunctable{example 1}{NiceArray}
The maximum of the \texttt{xvals} of \texttt{example 2}: \usefunctable{example 2}{maximum of xvals}
The list of \texttt{imgs} of \texttt{example 1}: \usefunctable{example 1}{list of imgs}
A \texttt{plot} for \texttt{example 2}: \usefunctable{example 2}{plot}
\end{document}
Ursprüngliche Antwort
Eine Umgebung functable
wird definiert. Sie nimmt ein obligatorisches Argument und danach den Textkörper an.
;
Der Text wird zuerst mit aufgeteilt \seq_set_split:Nnn
. Anschließend werden die Elemente auf aufgeteilt =
. Ein Schlüssel wie xvals
oder imgs
wird in gespeichert \l__projetmbc_key_tl
.
Ebenso wird ein Name wie t
oder f(t)
in gespeichert \l__projetmbc_name_tl
.
Die Umgebung functable
hängt vom ersten obligatorischen Argument ab. Nachfolgend finden Sie Beispiele für NiceArray
, maximum of xvals
, list of imgs
und plot
.
\documentclass[border=6pt,varwidth]{standalone}
\usepackage{nicematrix}
\usepackage{pgfplots}
\pgfplotsset{compat=1.18}
\ExplSyntaxOn
\cs_generate_variant:Nn \seq_map_indexed_inline:Nn { cn }
\cs_generate_variant:Nn \seq_set_from_clist:Nn { ce }
\seq_new:N \l__projetmbc_functable_seq
\seq_new:N \l__projetmbc_key_name_list_seq
\tl_new:N \l__projetmbc_coordinates_tl
\tl_new:N \l__projetmbc_key_tl
\tl_new:N \l__projetmbc_name_tl
\NewDocumentEnvironment { functable } { m +b }
{
\seq_set_split:Nnn \l__projetmbc_functable_seq { ; } {#2}
\seq_map_inline:Nn \l__projetmbc_functable_seq
{
\seq_set_split:Nnn \l__projetmbc_key_name_list_seq { = } {##1}
\int_compare:nNnT { \seq_count:N \l__projetmbc_key_name_list_seq } = { 2 }
{
\seq_pop_left:NN \l__projetmbc_key_name_list_seq \l__projetmbc_key_tl
\seq_clear_new:c { l__projetmbc_key_\l__projetmbc_key_tl _seq }
}
\seq_set_split:Nee \l__projetmbc_key_name_list_seq { \c_colon_str } { \seq_item:Nn \l__projetmbc_key_name_list_seq { 1 } }
\seq_pop_left:NN \l__projetmbc_key_name_list_seq \l__projetmbc_name_tl
\seq_put_right:cV { l__projetmbc_key_\l__projetmbc_key_tl _seq } \l__projetmbc_name_tl
\seq_clear_new:c { l__projetmbc_key_\l__projetmbc_key_tl _name_\l__projetmbc_name_tl _seq }
\seq_set_from_clist:ce { l__projetmbc_key_\l__projetmbc_key_tl _name_\l__projetmbc_name_tl _seq } { \seq_item:Nn \l__projetmbc_key_name_list_seq { 1 } }
}
\str_case:nnF {#1}
{
{ list~of~imgs }
{
\seq_use:Nn \l__projetmbc_key_imgs_seq { , ~ }
}
{ maximum~of~xvals }
{
\fp_eval:n { max ( \seq_use:cn { l__projetmbc_key_xvals_name_\seq_item:Nn \l__projetmbc_key_xvals_seq { 1 }_seq } { , } ) }
}
{ NiceArray }
{
$
\begin { NiceArray }
[ cell-space-limits = 3pt ]
{ c * { \seq_count:c { l__projetmbc_key_xvals_name_\seq_item:Nn \l__projetmbc_key_xvals_seq { 1 }_seq } } { | c } }
\seq_item:Nn \l__projetmbc_key_xvals_seq { 1 } & \seq_use:cn { l__projetmbc_key_xvals_name_\seq_item:Nn \l__projetmbc_key_xvals_seq { 1 }_seq } { & } \\ \hline
\seq_map_indexed_inline:Nn \l__projetmbc_key_imgs_seq
{
##2 & \seq_use:cn { l__projetmbc_key_imgs_name_##2_seq } { & }
\int_compare:nNnF {##1} = { \seq_count:N \l__projetmbc_key_imgs_seq }
{ \\ \hline }
}
\end { NiceArray }
$
}
{ plot }
{
\tl_build_begin:N \l__projetmbc_coordinates_tl
\seq_map_indexed_inline:cn { l__projetmbc_key_xvals_name_\seq_item:Nn \l__projetmbc_key_xvals_seq { 1 }_seq }
{
\tl_build_put_right:Ne \l__projetmbc_coordinates_tl
{ ( ##2 , \seq_item:cn { l__projetmbc_key_imgs_name_\seq_item:Nn \l__projetmbc_key_imgs_seq { 1 }_seq } {##1} ) }
}
\tl_build_end:N \l__projetmbc_coordinates_tl
\begin { tikzpicture }
\begin { axis }
[
ymin = 0
]
\addplot coordinates
{ \l__projetmbc_coordinates_tl }
;
\end { axis }
\end { tikzpicture }
}
}
{ \errmessage { wrong~option~for~functable~environment } }
}
{}
\ExplSyntaxOff
\begin{document}
Using \texttt{NiceArray}:
\begin{functable}{NiceArray}
xvals = t : 1 , 20 , 300 , 4000 ;
imgs = f(t) : a , bb , ccc , dddd ;
g(t) : U , VV , WWW , XXXX
\end{functable}
The maximum of the \texttt{xvals}:
\begin{functable}{maximum of xvals}
xvals = t : 1 , 20 , 300 , 4000 ;
imgs = f(t) : a , bb , ccc , dddd ;
g(t) : U , VV , WWW , XXXX
\end{functable}
The list of \texttt{imgs}:
\begin{functable}{list of imgs}
xvals = t : 1 , 20 , 300 , 4000 ;
imgs = f(t) : a , bb , ccc , dddd ;
g(t) : U , VV , WWW , XXXX
\end{functable}
A plot:
\begin{functable}{plot}
xvals = t : 1 , 2 , 3 , 4 ;
imgs = f(t) : 8 , 5 , 7 , 6 ;
\end{functable}
\end{document}