我正在研究 LaTeX 3 宏来获得如下所示的内容(我使用 ASCII 格式只是为了便于理解预期的输出):
x^2 - 2 = 0 or 4 x + 3 = 0 or x - 3 = 0
x^2 = 2 | 4 x = - 3 | x = 3
x = +/-sqrt(2) | x = - 3/4 |
API 看起来如下:
\orexpl{
x^2 - 2 = 0 \\
x^2 = 2 \\
x = \pm \sqrt{2}
---
4 x + 3 = 0 \\
4 x = - 3 \\
x = - \frac{3}{4}
---
x - 3 = 0 \\
x = 3
}
这是我拆分内容的起点---
,但我正在寻找完成这项工作的建议。我的想法是构建可以在类似表格的环境中使用的代码,例如由 提出的代码nicematrix
(实际上,我的小 M(not)WE 中的符号,
和;
将被和替换&
)\\
。
\documentclass{article}
\ExplSyntaxOn
\seq_new:N \l__pmbc_lines
\seq_new:N \l__pmbc_cells
\int_new:N \l__pmbc_nblines
\NewDocumentCommand{\orexpl}{+m} {
\seq_set_split:Nnn \l__pmbc_lines
{ --- }
{ #1 }
\int_set:Nn \l__pmbc_nblines
{ \seq_count:N \l__pmbc_lines }
}
\ExplSyntaxOff
\begin{document}
NO HOLE
\orexpl{
A1 \\ A2 \\ A3
---
B1 \\ B2 \\ B3
---
C1 \\ C2 \\ C3
}
Output wanted
A1 , B1 , C1 ;
A2 , B2 , C2 ;
A3 , B3 , C3 ;
\bigskip
WITH HOLES - CASE 1
\orexpl{
A1 \\ A2 \\ A3
---
B1
---
C1 \\ C2
}
Output wanted
A1 , B1 , C1 ;
A2 , , C2 ;
A3 , , ;
\bigskip
WITH HOLES - CASE 2
\orexpl{
A1
---
B1 \\ B2
---
C1 \\ C2 \\ C3
}
Output wanted
A1 , B1 , C1 ;
, B2 , C2 ;
, , C3 ;
\end{document}
答案1
expl3
这是使用和{NiceMatrix}
的解决方案nicematrix
。您需要最新版本nicematrix
(2021-04-08 的 v. 5.14)。
\documentclass{article}
\usepackage{nicematrix,tikz}
\ExplSyntaxOn
\seq_new:N \l__pmbc_lines_seq
\seq_new:N \l__pmbc_cells_seq
\int_new:N \l__pmbc_lines_int
\int_new:N \l__pmbc_cols_int
\cs_generate_variant:Nn \seq_set_split:Nnn { c n v }
\NewDocumentCommand { \orexpl } { +m }
{
\seq_set_split:Nnn \l__pmbc_lines_seq { --- } { #1 }
\int_set:Nn \l__pmbc_lines_int { \seq_count:N \l__pmbc_lines_seq }
%
% We create a sequence for each line called \l__pmbc_line_1_seq, \l__pmbc_line_2_seq, etc.
% Recall that ##1 is the index of the loop: ##1 will vary from 1 to \l__pmbc_lines_int
\int_step_inline:nn \l__pmbc_lines_int
{
\tl_set:cx { l__pmbc_line_ ##1 _tl } { \seq_item:Nn \l__pmbc_lines_seq { ##1 } }
\seq_set_split:cnv { l__pmbc_line_ ##1 _seq } { \\ } { l__pmbc_line_ ##1 _tl }
}
%
% We compute in \l__pmbc_cols_int the maximum of the length of the previous sequences: it's the
% number of columns of the input (the array given by the user).
\int_step_inline:nn \l__pmbc_lines_int
{
\int_set:Nn \l_tmpa_int { \seq_count:c { l__pmbc_line_ ##1 _seq } }
\int_compare:nNnT \l_tmpa_int > \l__pmbc_cols_int
{ \int_set_eq:NN \l__pmbc_cols_int \l_tmpa_int }
}
\begin{NiceMatrix}
%
% Now, two imbricated loops. ##1 is the index of the first loop and ####1 is the index of the second loop.
\int_step_inline:nn \l__pmbc_cols_int
{
\int_compare:nNnF ##1 > { \seq_count:c { l__pmbc_line_1_seq } }
{ \seq_item:cn { l__pmbc_line_1_seq } { ##1 } }
\int_step_inline:nnn 2 \l__pmbc_lines_int
{
\int_compare:nNnTF ##1 > { \seq_count:c { l__pmbc_line_ ####1 _seq } }
{ & & }
{
&
% The words "or" will be in a standalone column (the vertical rule below will be drawn by Tikz)
\int_compare:nNnT { ##1 } = 1 { \text { or } }
&
\seq_item:cn { l__pmbc_line_ ####1 _seq } { ##1 }
}
}
\int_compare:nNnF \l__pmbc_cols_int = ##1 { \\ }
}
%
% We draw the vertical rules in the columns by using the PGF/Tikz constructed by {NiceMatrix}
\CodeAfter
\int_step_inline:nn { \l__pmbc_lines_int - 1 }
{
\tikz \draw ( 2 -| \int_eval:n { 2 * ##1 } .5 )
-- (last -| \int_eval:n { 2 * ##1 } .5 ) ;
}
\end{NiceMatrix}
}
\ExplSyntaxOff
\begin{document}
$\orexpl{
x^2 - 2 = 0 \\
x^2 = 2 \\
x = \pm \sqrt{2}
---
4 x + 3 = 0 \\
4 x = - 3 \\
x = - \frac{3}{4}
---
x - 3 = 0 \\
x = 3 \\
}$
\bigskip
$\orexpl{A1 --- B1 --- C1 \\ C2 \\ C3}$
\bigskip
$\orexpl{A1--- B1 \\ B2 --- C1 \\ C2 \\ C3}$
\end{document}
与往常一样,nicematrix
您需要进行多次编译(因为nicematrix
在后台使用 PGF/Tikz 节点)。
答案2
这里,我使用分隔符listofitems
来解析输入---
。列表中的每个项目都可以直接用作堆栈。我实际上进行了嵌套解析,还读取了\\
每个堆栈中的分隔符数量,并使用此信息来计算堆栈之间的规则深度。
我在其中一个示例中改变了列表深度,只是为了表明规则深度不是固定的,而是随着列表深度进行调整。
我还改变了堆栈的基线跳跃,规则会自动调整到设置。
[align]
如果您希望提供制表符(在 之后,而不是 之前) ,请编辑以添加一个选项=
。否则,对齐方式为左对齐。
\documentclass{article}
\usepackage{listofitems,tabstackengine}
\newcommand\orexpl[2][]{%
\setsepchar{---/\\}
\readlist*\myvecs{#2}%
\def\listdepth{1}%
\foreachitem\z\in\myvecs[]{%
\ifnum\listlen\myvecs[\zcnt]>\listdepth\relax
\xdef\listdepth{\listlen\myvecs[\zcnt]}%
\fi
}%
\renewcommand\stackalignment{l}%
\foreachitem\z\in\myvecs[]{%
\ifnum\zcnt=1\relax\else\Shortunderstack[c]{\quad or\quad\\\rule
{.4pt}{\numexpr\listdepth-1\relax\dimexpr\Lstackgap\relax}}\fi
\ensurestackMath{\csname #1Longunderstack\expandafter
\endcsname\expandafter{\z}}%
}%
}
\begin{document}
\orexpl[align]{
x^2 - 2 =& 0 \\
x^2 =& 2 \\
x =& \pm \sqrt{2}
---
4 x + 3 =& 0 \\
4 x =& - 3 \\
x =& - \frac{3}{4}
---
x - 3 =& 0 \\
x =& 3
}
\bigskip
\orexpl{
A123 \\ A2 \\ A3 \\ A4
---
B1 \\ B2 \\ B3
---
C1 \\ C2 \\ C3
}
\setstackgap{L}{.8\baselineskip}
\bigskip
\orexpl{
A1 \\ A2 \\ A3
---
B1
---
C1 \\ C2
}
\setstackgap{L}{1.3\baselineskip}
\bigskip
\orexpl{
A1
---
B1 \\ B2
---
C1 \\ C2 \\ C3
}
\end{document}
答案3
这是转置的基础:
\documentclass{article}
\usepackage{amsmath}
\ExplSyntaxOn
\NewDocumentCommand{\orexpl}{m}
{
\pmbc_orexpl:n { #1 }
}
\cs_generate_variant:Nn \seq_set_split:Nnn { c }
\seq_new:N \l_pmbc_orexpl_lines_seq
\int_new:N \l_pmbc_orexpl_cols_int
\int_new:N \l_pmbc_orexpl_rows_int
% allocate at least three columns
\seq_new:c { l_pmbc_orexpl_col_1_seq }
\seq_new:c { l_pmbc_orexpl_col_2_seq }
\seq_new:c { l_pmbc_orexpl_col_3_seq }
% and three rows
\seq_new:c { l_pmbc_orexpl_row_1_seq }
\seq_new:c { l_pmbc_orexpl_row_2_seq }
\seq_new:c { l_pmbc_orexpl_row_3_seq }
\cs_new_protected:Nn \pmbc_orexpl:n
{
\seq_set_split:Nnn \l_pmbc_orexpl_lines_seq { --- } { #1 }
\int_set:Nn \l_pmbc_orexpl_cols_int { \seq_count:N \l_pmbc_orexpl_lines_seq }
\int_zero:N \l_pmbc_orexpl_rows_int
% get the column data
\seq_map_indexed_inline:Nn \l_pmbc_orexpl_lines_seq
{
\seq_clear_new:c { l_pmbc_orexpl_col_##1_seq }
\seq_set_split:cnn { l_pmbc_orexpl_col_##1_seq } { \\ } { ##2 }
\int_set:Nn \l_pmbc_orexpl_rows_int
{
\int_max:nn { \l_pmbc_orexpl_rows_int } { \seq_count:c { l_pmbc_orexpl_col_##1_seq } }
}
}
% now transpose
\int_step_inline:nn { \l_pmbc_orexpl_rows_int }
{
\seq_clear_new:c { l_pmbc_orexpl_row_##1_seq }
\int_step_inline:nn { \l_pmbc_orexpl_cols_int }
{
\seq_put_right:cx { l_pmbc_orexpl_row_##1_seq }
{
\seq_item:cn { l_pmbc_orexpl_col_####1_seq } { ##1 }
}
}
}
% and build the array
\begin{array}{ c *{ \int_eval:n { \l_pmbc_orexpl_cols_int - 1 } } { |c } }
\int_step_function:nN { \l_pmbc_orexpl_rows_int } \__pmbc_orexpl_makerow:n
\end{array}
}
\cs_new_protected:Nn \__pmbc_orexpl_makerow:n
{
\seq_use:cn { l_pmbc_orexpl_row_#1_seq } { & } \\
}
\ExplSyntaxOff
\begin{document}
\[
\orexpl{
x^2 - 2 = 0 \\
x^2 = 2 \\
x = \pm \sqrt{2}
---
4 x + 3 = 0 \\
4 x = - 3 \\
x = - \frac{3}{4}
---
x - 3 = 0 \\
x = 3
}
\]
\end{document}
使用“或”分隔符:
\documentclass{article}
\usepackage{amsmath,array}
\ExplSyntaxOn
\NewDocumentCommand{\orexpl}{m}
{
\group_begin:
\setlength{\arraycolsep}{2em}
\pmbc_orexpl:n { #1 }
\group_end:
}
\cs_generate_variant:Nn \seq_set_split:Nnn { c }
\cs_generate_variant:Nn \seq_map_indexed_inline:Nn { c }
\seq_new:N \l_pmbc_orexpl_lines_seq
\int_new:N \l_pmbc_orexpl_cols_int
\int_new:N \l_pmbc_orexpl_rows_int
% allocate at least three columns
\seq_new:c { l_pmbc_orexpl_col_1_seq }
\seq_new:c { l_pmbc_orexpl_col_2_seq }
\seq_new:c { l_pmbc_orexpl_col_3_seq }
% and three rows
\seq_new:c { l_pmbc_orexpl_row_1_seq }
\seq_new:c { l_pmbc_orexpl_row_2_seq }
\seq_new:c { l_pmbc_orexpl_row_3_seq }
\cs_new_protected:Nn \pmbc_orexpl:n
{
\seq_set_split:Nnn \l_pmbc_orexpl_lines_seq { --- } { #1 }
\int_set:Nn \l_pmbc_orexpl_cols_int { \seq_count:N \l_pmbc_orexpl_lines_seq }
\int_zero:N \l_pmbc_orexpl_rows_int
% get the column data
\seq_map_indexed_inline:Nn \l_pmbc_orexpl_lines_seq
{
\seq_clear_new:c { l_pmbc_orexpl_col_##1_seq }
\seq_set_split:cnn { l_pmbc_orexpl_col_##1_seq } { \\ } { ##2 }
\int_set:Nn \l_pmbc_orexpl_rows_int
{
\int_max:nn { \l_pmbc_orexpl_rows_int } { \seq_count:c { l_pmbc_orexpl_col_##1_seq } }
}
}
% now transpose
\int_step_inline:nn { \l_pmbc_orexpl_rows_int }
{
\seq_clear_new:c { l_pmbc_orexpl_row_##1_seq }
\int_step_inline:nn { \l_pmbc_orexpl_cols_int }
{
\seq_put_right:cx { l_pmbc_orexpl_row_##1_seq }
{
\seq_item:cn { l_pmbc_orexpl_col_####1_seq } { ##1 }
}
}
}
% and build the array
\__pmbc_orexpl_makerow_first:
\begin{array}{ c *{ \int_eval:n { \l_pmbc_orexpl_cols_int - 1 } } { |c } }
\tl_use:N \l_tmpa_tl \\
\int_step_function:nnN { 2 } { \l_pmbc_orexpl_rows_int } \__pmbc_orexpl_makerow:n
\end{array}
}
\cs_new_protected:Nn \__pmbc_orexpl_makerow_first:
{
\tl_clear:N \l_tmpa_tl
\seq_map_indexed_inline:cn { l_pmbc_orexpl_row_1_seq }
{
\int_compare:nTF { ##1 < \seq_count:c { l_pmbc_orexpl_row_1_seq } }
{ \tl_put_right:Nn \l_tmpa_tl { \multicolumn{1}{c!{\__pmbc_orexpl_or:}}{##2} & } }
{ \tl_put_right:Nn \l_tmpa_tl { ##2 } }
}
}
\cs_new_protected:Nn \__pmbc_orexpl_or:
{
\makebox[0pt]{\makebox[2\arraycolsep]{~or~}}
}
\cs_new_protected:Nn \__pmbc_orexpl_makerow:n
{
\seq_use:cn { l_pmbc_orexpl_row_#1_seq } { & } \\
}
\ExplSyntaxOff
\begin{document}
\[
\orexpl{
x^2 - 2 = 0 \\
x^2 = 2 \\
x = \pm \sqrt{2}
---
4 x + 3 = 0 \\
4 x = - 3 \\
x = - \frac{3}{4}
---
x - 3 = 0 \\
x = 3
}
\]
\end{document}