下面的代码取自这个帖子。是否可以创建一个包含所有不同年份的序列/数组,以及另一个包含每年有多少个条目的序列/数组?
\documentclass{tufte-book}
\usepackage{datenumber, ifthen, xparse}
\usepackage{lipsum}
\setstartyear{2000}
\newcounter{day}
\ExplSyntaxOn
% Declare variables
\seq_new:N \g_journal_seq
\seq_new:N \g_journal_out_seq
\iow_new:N \g_journal_stream
\tl_new:N \l_journal_date_tl
% At the beginning of the run, read the lines of the `.jrn` file into a sequence.
% These are the dates. If the file can not be opened, it probably does not exists
% and we treat it as empty.
\cs_new:Npn \readjournaldates {
\ior_open:NnT \g_journal_stream { \c_sys_jobname_str.jrn } {
\ior_map_inline:Nn \g_journal_stream {
\seq_gput_right:Nn \g_journal_seq { ##1 }
}
\ior_close:N \g_journal_stream
}
}
% The main environment:
\NewDocumentEnvironment{ newday }{ O{} }{
\stepcounter{day}
% If the sequence \g_journal_seq is not empty yet, then we already saved a date
% for the current day. Save this day in `\l_journal_date_tl` and delete it from
% the sequence. Otherwise we have not saved anything yet, so we choose the current
% date.
\seq_gpop_left:NNF \g_journal_seq \l_journal_date_tl {
\tl_set:Nx \l_journal_date_tl {\datedayname,~\today}
}
% Now we have to save the choosen date for the next run. First, only store it in the
% sequence `\g_journal_out_seq`, we only write it to the file at the end to avoid
% overwriting the file if something fails:
\seq_gput_right:NV \g_journal_out_seq \l_journal_date_tl
\textbf{ #1 }
\marginnote{ \l_journal_date_tl } \\
}{
\vspace{0.5cm}
}
% At the end of the document, iterate over `\g_journal_out_seq` and write every entry
% into a line
\AtEndDocument{
\iow_open:Nn \g_journal_stream { \c_sys_jobname_str.jrn }
\seq_map_inline:Nn \g_journal_out_seq {
\iow_now:Nn \g_journal_stream { #1 }
}
\iow_close:N \g_journal_stream
}
\ExplSyntaxOff
\makeatletter
\readjournaldates
\makeatother
% ---------------
\begin{document}
\begin{newday}[A day]
\lipsum[1]
\end{newday}
\begin{newday}[Yet another day]
\lipsum[2]
\end{newday}
\begin{newday}
\lipsum[3]
\end{newday}
\end{document}
比如说,我们将两个数组分别命名为\years
和\entriesperyear
,假设一共输入了四天,其中三天是2018年,一天是2019年。那么应该是:
\years(1) = 2018, \years(2) = 2019, \entriesperyear(1) = 3, \entriesperyear(2) = 1
答案1
这个答案实际上并没有使用数组,而是使用属性列表。这是一个 expl3 数据结构,允许使用 迭代条目,\prop_map_inline:Nn
或使用 访问单个条目\prop_get:NnN
。作为演示,我们将在日记的末尾打印一个列表,其中包含每年的条目数:
\documentclass{tufte-book}
\usepackage{datenumber, ifthen, xparse}
\usepackage{lipsum}
\setstartyear{2000}
\newcounter{day}
\ExplSyntaxOn
\cs_generate_variant:Nn \prop_get:NnNF { NfNF }
\cs_generate_variant:Nn \prop_gput:Nnn { Nff }
% Declare variables
\seq_new:N \g_journal_seq
\seq_new:N \g_journal_out_seq
\iow_new:N \g_journal_stream
\tl_new:N \l_journal_date_tl
\prop_new:N \g_journal_years_prop
% At the beginning of the run, read the lines of the `.jrn` file into a sequence.
% These are the dates. If the file can not be opened, it probably does not exists
% and we treat it as empty.
\cs_new:Npn \readjournaldates {
\ior_open:NnT \g_journal_stream { \c_sys_jobname_str.jrn } {
\ior_map_inline:Nn \g_journal_stream {
\seq_gput_right:Nn \g_journal_seq { ##1 }
\prop_get:NfNF \g_journal_years_prop { \tl_head:n { ##1 } } \l_tmpa_tl {
\tl_set:Nn \l_tmpa_tl { 0 }
}
\prop_gput:Nff \g_journal_years_prop { \tl_head:n { ##1 } } {
\int_eval:n { \l_tmpa_tl + 1 }
}
}
\ior_close:N \g_journal_stream
}
}
% The main environment:
\NewDocumentEnvironment{ newday }{ O{} }{
\stepcounter{day}
% If the sequence \g_journal_seq is not empty yet, then we already saved a date
% for the current day. Save this day in `\l_journal_date_tl` and delete it from
% the sequence. Otherwise we have not saved anything yet, so we choose the current
% date.
\seq_gpop_left:NNF \g_journal_seq \l_journal_date_tl {
\tl_set:Nx \l_journal_date_tl { { \int_use:N \c_sys_year_int } \datedayname,~\today}
\prop_get:NfNF \g_journal_years_prop { \int_use:N \c_sys_year_int } \l_tmpa_tl {
\tl_set:Nn \l_tmpa_tl { 0 }
}
\prop_gput:Nff \g_journal_years_prop { \int_use:N \c_sys_year_int } {
\int_eval:n { \l_tmpa_tl + 1 }
}
}
% Now we have to save the choosen date for the next run. First, only store it in the
% sequence `\g_journal_out_seq`, we only write it to the file at the end to avoid
% overwriting the file if something fails:
\seq_gput_right:NV \g_journal_out_seq \l_journal_date_tl
\textbf{ #1 }
\marginnote{ \tl_tail:N \l_journal_date_tl } \\
}{
\vspace{0.5cm}
}
% At the end of the document, iterate over `\g_journal_out_seq` and write every entry
% into a line
\AtEndDocument{
\iow_open:Nn \g_journal_stream { \c_sys_jobname_str.jrn }
\seq_map_inline:Nn \g_journal_out_seq {
\iow_now:Nn \g_journal_stream { #1 }
}
\iow_close:N \g_journal_stream
}
\ExplSyntaxOff
\makeatletter
\readjournaldates
\makeatother
% ---------------
\begin{document}
\begin{newday}[A day]
\lipsum[1]
\end{newday}
\begin{newday}[Yet another day]
\lipsum[1]
\end{newday}
\begin{newday}
Today I couldn't even think about a title.
\end{newday}
\begin{newday}[Yet another day]
Some very interesting text.
\end{newday}
\ExplSyntaxOn
\prop_map_inline:Nn \g_journal_years_prop {
During~#1~there~have~been~#2~entries.~
}
% If you really want two "arrays"
\seq_new:N \g_journal_years_seq
\seq_new:N \g_journal_yearentries_seq
\prop_map_inline:Nn \g_journal_years_prop {
\seq_gput_right:Nn \g_journal_years_seq { #1 }
\seq_gput_right:Nn \g_journal_yearentries_seq { #2 }
}
\cs_new:Npn \years #1 {
\seq_item:Nn \g_journal_years_seq { #1 }
}
\cs_new:Npn \entriesperyear #1 {
\seq_item:Nn \g_journal_yearentries_seq { #1 }
}
\ExplSyntaxOff
In \years{2} we got \entriesperyear{2} entries.
\end{document}