打印键值对的最佳方式:表、数组还是矩阵?

打印键值对的最佳方式:表、数组还是矩阵?

我有一系列值需要按行打印在多列中。(这些值作为\def变量保存,由程序生成,其中一些可以是空字符串。)

问题是如何避免出现空单元格,并让下一个单元格自动取代前一个单元格的位置(如果前一个单元格是空的)。例如,我有以下非空值:,,,,,,排列成Author3列,如下所示:ComposerPublisherYear

Author    Composer    Publisher

Year

那是两行。如果我们再添加一个条目,它应该进入下一个单元格Year

但是,如果出版商为空,则年份应自动出现在第一行:

Author    Composer    Year

我有\Author\Composer\Publisher\Year需要按此方式排列的变量列表。我只想写类似这样的内容:

\SomeEnvironment{\Author, \Composer, \Publisher, \Year, \something so on}

并让环境自动找出删除空的并让下一个流动。

如何实现这一点?

PS:对于那些好奇的人来说,这是卡姆蒂:卡纳提克音乐排版环境项目。

答案1

不确定你想要的是纯文本还是乳胶文本,虽然这是一个纯文本文档,但宏应该可以与两者配合使用

\def\SomeEnvironment#1{%
  \par\noindent
  \xSomeEnvironment #1\relax}

\def\xSomeEnvironment#1{%
  \ifx\relax#1%
  \hfill
  \else
  \ifx\empty#1%
  \else
   \hbox to 0.3333\hsize{#1\hfill}\hfil
  \fi
  \expandafter\xSomeEnvironment 
  \fi}

\def\Author{Author}
\def\Composer{Composer}
\def\Publisher{}
\def\Year{Year}
\def\something{something}
\def\somethingelse{somethingelse}

\SomeEnvironment{\Author \Composer \Publisher \Year \something \somethingelse} 

\bye

在此处输入图片描述

这个循环会检查每个标记,如果是,则\relax停止;如果定义相同,则\empty跳过该标记;否则,它会将内容设置在文本宽度为 1/3(0.333330)的框中。因此,不需要明确的换行或对齐点,当段落以通常的方式分成几行时,唯一可能发生换行的地方是每三个条目一次,因为框永远不会换行。要获得更多列,只需更改 0.33333,例如 0.25 会给您四列。

编辑:

您的实际情况有点复杂,因为您不只是一个标记,您要么想要一个大括号组,要么\var后面跟着一个大括号组,而且您的定义不是空的,而是由于\relax怪异而定义的\csname

\documentclass{article}

\newcommand{\var}[1]{\csname #1\endcsname}
\newcommand{\DefVar}[2]{\expandafter\newcommand\csname #1\endcsname{#2}}
\newcommand{\SetVar}[2]{\ifcsname #1\endcsname
                         \expandafter\renewcommand\csname #1\endcsname{#2}
                         \else \DefVar{#1}{#2} \fi}
\newcommand{\Var}{\var}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\def\SomeEnvironment#1{%
  \par\noindent
  \xSomeEnvironment #1\relax}

\def\xSomeEnvironment#1{%
  \ifx\var#1\relax
  \expandafter\xxxSomeEnvironment
  \else
  \ifx\relax#1\relax
  \hfill
  \else
  \def\tempa{#1}%
  \expandafter\expandafter\expandafter\xxSomeEnvironment
  \expandafter\expandafter\expandafter\tempa
  \fi
  \fi}

\def\xxSomeEnvironment#1{%
  \hbox to 0.3333\hsize{#1\hfill}\hfil
  \expandafter\xSomeEnvironment 
  }

\def\xxxSomeEnvironment#1{%
  \expandafter\let\expandafter\tempa\csname#1\endcsname
  \ifx\relax\tempa
  \expandafter\xSomeEnvironment 
  \else
  \expandafter\xxSomeEnvironment\csname#1\expandafter\endcsname
  \fi}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{document}

\def\index[#1]#2{}




% Below attributes are programatically set by user in the CarMusTy Document
% 
% Note that these could be unicode values in real documents, hence we need these as \csname in the \var{} definitions
%
% Als note that if a variable is not set any value, such as Song2Composer below, it will not be defined (which is fine because the \var{} allows it to be \relax)
%  For testing these are commented out below, making them undefined.
%
\DefVar{BookTOC}{Book Title}
\DefVar{BookTitle}{Book Title}
\DefVar{BookSubTitle}{Sub Title}
\DefVar{BookAuthor}{Book Author}
\DefVar{BookPublisher}{Book Publisher}
\DefVar{BookYear}{Book Year}
\DefVar{Song1Title}{Song Title1}
\DefVar{Song1Author}{Author1\index[Author]{Author1!\var{SongTitle}}}
\DefVar{Song1Composer}{Composer1\index[Composer]{Composer1!\var{SongTitle}}}
\DefVar{Song1Singers}{Singers1\index[Singers]{Singers1!\var{SongTitle}}}
\DefVar{Song1Movie}{Movie1\index[Movie]{Movie1!\var{SongTitle}}}
\DefVar{Song1Year}{Year1}
\DefVar{Song1Raga}{RAGAVARDHINI\index[Raga]{RAGAVARDHINI!\var{SongTitle}}}
\DefVar{Song1Tala}{tripuTa\index[Tala]{tripuTa!\var{SongTitle}}}
\DefVar{Song1Verse1Title}{Verse}
\DefVar{Song1Verse2Title}{Verse}
\DefVar{Song2Title}{Song Title2}
\DefVar{Song2Author}{Author2\index[Author]{Author2!\var{SongTitle}}}
%\DefVar{Song2Composer}{Composer1\index[Composer]{Composer1!\var{SongTitle}}}
\DefVar{Song2Singers}{Singers1\index[Singers]{Singers1!\var{SongTitle}}}
\DefVar{Song2Movie}{Movie2\index[Movie]{Movie2!\var{SongTitle}}}
\DefVar{Song2Year}{Year2}
\DefVar{Song2Raga}{Raga2\index[Raga]{Raga2!\var{SongTitle}}}
%\DefVar{Song2Tala}{Tala2\index[Tala]{Tala2!\var{SongTitle}}}
\DefVar{Song2Verse1Title}{Verse}
\DefVar{Song2Verse2Title}{Verse}

%%%%%%%%%%%%%%%%%%%%%%%%
%%%%% Lets Print them

\section*{}
{\huge{Song Title}}
\SomeEnvironment{{Author} {Composer} {Singers} {Movie} {Year} }

% Uncomment the below lines to see the error
\section*{}
{\huge\var{Song1Title}}
\SomeEnvironment{\var{Song1Author} \var{Song1Composer} \var{Song1Singers} \var{Song1Movie} \var{Song1Year}} % << - Uncomment this line to see the error

\section*{}
{\huge\var{Song2Title}}
\SomeEnvironment{\var{Song1Author} \var{Song1Composer} \var{Song1Singers} \var{Song1Movie} \var{Song1Year}}  % << - Uncomment this line to see the error

\end{document}

答案2

好吧,我违抗了键值系统专利持有者大卫卡莱尔的命令,决定采用键值语法。

\documentclass{article}
\usepackage{keyreader}[2012/01/14]
\usepackage{catoptions}[2011/12/17]
% Load geometry to enlarge the print area:
\usepackage[left=2cm,right=2cm]{geometry}

\makeatletter
\new@def*\var#1{\usename{carm@#1}}
\newletcs\Var\var
\def\Arrange#1{\par\noindent\xArrange#1\@nnil}
\def\xArrange#1{%
  \expandafter\ifcseqTF\@car#1\@nil\var{%
    \xxArrange
  }{%
    \expandafter\ifcseqTF\@car#1\@nil\@nnil{%
      \hfill
    }{%
      \hb@xt@\dimexpr\carm@alignment{#1\hfill}\hfil
      \xArrange
    }%
  }%
}
\def\xxArrange#1{%
  \ifcsndefFT{carm@\cpttrimspaces{#1}}{}{%
    \hb@xt@\dimexpr\carm@alignment{\@nameuse{carm@\cpttrimspaces{#1}}\hfill}\hfil
  }%
  \xArrange
}
% I don't want us to redefine \index, which is a LaTeX command. Hence
% I use \iindex instead. I assume that \iindex has one optional argument.
\new@def*\iindex{\cpt@testopt\iindex@a{}} % no \robust@def here!
\new@def*\iindex@a[#1]#2{}

\robust@def*\carm@getcallback#1#2{%
  \def\@tempa##1#1##2\carm@nil{%
    \edef\call@back{\cpttrimspaces{##2}}%
    \carm@split##1==\carm@nil
  }%
  \@tempa#2\carm@nil
}
\robust@def*\carm@split#1=#2=#3\carm@nil{%
  \edef\@tempa{\cpttrimspaces{#1}}%
  \edef\@tempb{\cpttrimspaces{#2}}%
  \edef\key@values{\csliststack,\key@values
    \expandcsonce\@tempa=\expandcsonce\@tempb}%
  \ifcsndefFT{CARM@carmusty@\@tempa}{}{%
    \if@carmst
      \@latex@error{CarMusty key '\@tempa' redefined}\@ehc
    \else
      \@latex@warning@no@line{CarMusty key '\@tempa' redefined}%
    \fi
  }%
  \cptexpandsecond{\define@cmdkey[CARM]{carmusty}[carm@]}%
    {{\expandcsonce\@tempa}[{\expandcsonce\@tempb}]%
    {\expandcsonce\call@back}}%
}
\robust@def*\carmustykeys{\cpt@teststopt\carmustykeys@a{define}}
\robust@def*\carmustykeys@a[#1]{%
  \let\if@carmst\ifcpt@st
  \begingroup
  \endlinechar\m@ne
  \xifstrcmpTF{\cpttrimspaces{#1}}{define}{%
    \definecarmustykeys
  }{%
    \xifstrcmpTF{\cpttrimspaces{#1}}{set}{%
      \setcarmustykeys
    }{%
      \@latex@error{Unknown carmusty action '\detokenize{#1}'}\@ehc
    }%
  }%
}
\robust@def*\definecarmustykeys#1{%
  \endgroup
  \def\key@values{}%
  \cptdocommalist{#1}{%
    \ifinsetTF{.code=}{##1}{%
      \carm@getcallback{.code=}{##1}%
    }{%
      \ifinsetTF{.code =}{##1}{%
        \carm@getcallback{.code =}{##1}%
      }{%
        \carm@getcallback{.code=}{##1.code=}%
      }%
    }%
  }%
  \cptexpandargonce{\krdsetkeys[CARM]{carmusty}}\key@values
}
\robust@def*\setcarmustykeys#1{%
  \endgroup
  \cptexpandsecond\krdsetkeys{\if@carmst*\fi}[CARM]{carmusty}{#1}%
}

% When defining keys, the star (*) variant of \carmustykeys will
% raise an error when an existing key is being redefined.

% When setting keys, the star (*) variant of \carmustykeys will use
% the star variant of \setkeys. See the documentation of 'keyreader'
% or 'xkeyval' to see the meaning of the starred form of \setkeys.
% Actually, we don't use \setkeys but the more robust \krdsetkeys.

% Examples:
\carmustykeys*[define]{%
  keya = .3333\hsize .code = \def\x##1{#1##1},
  % Uncomment the following line to get an error (keya is being redefined):
  % keya = default of keya .code = \def\result{generate error}
}
\carmustykeys*[set]{%
  keya = valuea
}

% Real business:
\carmustykeys{%
  alignment = .3333\hsize,
  BookTOC = Book Title,
  BookTOC = Book Title, % redefined - see log file for warning
  BookTitle = Book Title,
  BookSubTitle = Sub Title,
  BookAuthor = Book Author,
  BookPublisher = Book Publisher,
  BookYear = Book Year,
  Song1Title = Song Title1,
  Song1Author = Author1\iindex[Author]{Author1!\var{SongTitle}},
  Song1Composer = Composer1\iindex[Composer]{Composer1!\var{SongTitle}},
  Song1Singers = Singers1\iindex[Singers]{Singers1!\var{SongTitle}},
  Song1Movie = Movie1\iindex[Movie]{Movie1!\var{SongTitle}},
  Song1Year = Year1,
  Song1Raga = RAGAVARDHINI\iindex[Raga]{RAGAVARDHINI!\var{SongTitle}},
  Song1Tala = tripuTa\iindex[Tala]{tripuTa!\var{SongTitle}},
  Song1Verse1Title = Verse,
  Song1Verse2Title = Verse,
  Song2Title = Song Title2,
  Song2Author = Author2\iindex[Author]{Author2!\var{SongTitle}},
  Song2Composer = Composer1\iindex[Composer]{Composer1!\var{SongTitle}},
  Song2Singers = Singers1\iindex[Singers]{Singers1!\var{SongTitle}},
  Song2Movie = Movie2\iindex[Movie]{Movie2!\var{SongTitle}},
  Song2Year = Year2,
  Song2Raga = Raga2\iindex[Raga]{Raga2!\var{SongTitle}},
  Song2Tala = Tala2\iindex[Tala]{Tala2!\var{SongTitle}},
  Song2Verse1Title = Verse,
  Song2Verse2Title = Verse,
}
\makeatother

% If needed, you can add new keys by doing:
% \carmustykeys[define]{key1=value1,<...>,key2=value2}

% To change the alignment, you can do:
% \carmustykeys[set]{alignment=<some value>}

% Let's print them:
\begin{document}
\parindent0pt
\carmustykeys[set]{alignment=.1333\hsize}

\textbf{Song Title}
\Arrange{{Author} {Composer} {Singers} {Movie} {Year} }

\par\medskip
\textbf{\var{Song1Title}}
\Arrange{\var{Song1Author} \var{Song1Composer} \var{Song1Singers}
  \var{Song1Movie} \var{Song1Year} \var{Song1Verse2Title}}

\par\medskip
\textbf{\var{Song2Title}}
\Arrange{\var{Song1Author} \var{Song1Composer} \var{Song1Singers}
  \var{Song1Movie} \var{Song1Year}}
\end{document}

在此处输入图片描述

相关内容