Я пытаюсь создать документ Latex, в котором я определяю список элементов (например, фруктов) в начале, чтобы изменить результирующий текст/внешний вид документа в зависимости от количества определенных мной элементов.
Поэтому я определил функцию, \newcommand{\length}
которая должна подсчитывать количество предметов (фруктов) и «возвращать» число.
Этот минимальный (не)рабочий пример должен проиллюстрировать то, чего я пытаюсь добиться:
\documentclass{article}
\makeatletter
\newcounter{numlength}%
\newcommand{\length}[1]{%
\setcounter{numlength}{0}%
\@for\element:=#1\do{\stepcounter{numlength}}%
\value{numlength}% Variant 1
% \arabic{numlength}% Variant 2
% \thenumlength% Variant 3
}
\makeatother
\def\fruits{apple,banana,mango}
\begin{document}
\section{Fruits}
Number of fruits: \length{\fruits}
\\There \ifnum\length{\fruits}=1 is just a single fruit\else are multiple fruits\fi on my list:
\\\fruits
\end{document}
Печать числа в моем тексте ( Number of fruits: \length{\fruits}
) работает только с вариантами 2 и 3 (что я понимаю), но использование числа в \ifnum
не работает, независимо от того, какой вариант я использую.
Для ясности: меня не интересует удобный способ печати самих элементов (фруктов); меня больше всего волнует использование числа, которое я «вычисляю» в \newcommand{\length}
условии \ifnum
.
Кроме того, если это возможно, я бы хотел воздержаться от использования каких-либо пакетов ( \usepackage
).
Если вам понадобится дополнительная информация, сообщите мне, пожалуйста. Заранее спасибо!
решение1
Как отмечает @DavidCarlisle в своем комментарии, в TeX необходимо обеспечить расширяемость, если вы хотите использовать макрос там, где TeX ожидает число, поэтому вы не можете использовать присваивания.
У вас есть два варианта решения вашей проблемы:
Выполните задания первого шага и используйте результат для своего
\ifnum
.Подсчитайте количество фруктов с помощью расширяемой функции.
Следующий пример реализует последнее с использованием функции/макроса из L3:
\documentclass{article}
\ExplSyntaxOn
\cs_generate_variant:Nn \clist_count:n { V }
\cs_new_eq:NN \length \clist_count:V
\ExplSyntaxOff
\newcommand*\fruits{apple,banana,mango}
\begin{document}
\section{Fruits}
Number of fruits: \length{\fruits}
\\There \ifnum\length{\fruits}=1 is just a single fruit\else are multiple fruits\fi on my list:
\\\fruits
\end{document}
Техническая информация, вы можете проигнорировать это и просто использовать вышеизложенное:
В отличие от моего комментария, код в этом ответе использует V
вариант, поскольку ваш \fruit
не установлен с помощью одной из -функций clist
L3, это должно быть семантически чище, поскольку V
выполнит шаги по очистке, необходимые для получения правильных результатов, в отличие от N
.
При первом подходе:
Для того, чтобы первый подход сработал, вам не нужно менять слишком много в вашем фактическом коде. Вам просто нужно удалить прямой вывод, а вместо этого на втором шаге использовать значение вашего numlength
счетчика:
\documentclass{article}
\makeatletter
\newcounter{numlength}%
\newcommand{\length}[1]{%
\setcounter{numlength}{0}%
\@for\element:=#1\do{\stepcounter{numlength}}%
}
\makeatother
\def\fruits{apple,banana,mango}
\begin{document}
\section{Fruits}
Number of fruits: \length{\fruits}\arabic{numlength}
\\There \length\fruits\ifnum\value{numlength}=1 is just a single fruit\else are multiple fruits\fi on my list:
\\\fruits
\end{document}
(вывод как выше)
решение2
Как уже объясняли другие, сначала нужно сохранить длину в макросе, а затем использовать \ifnum
. Но этот метод громоздкий и сам по себе не расширяемый.
Я предлагаю метод, который не требует \def
, поэтому вы не рискуете затирать существующие команды (и «изобретать» новые).
Вы также можете добавлять списки и делать более сложные разветвления на основе количества элементов. Списки должны быть непустыми.
Обратите внимание, что \branchonlist
он полностью расширяемый.
\documentclass{article}
\ExplSyntaxOn
\NewDocumentCommand{\definelist}{mm}
{
\clist_clear_new:c { l_lennart_list_#1_clist }
\clist_set:cn { l_lennart_list_#1_clist } { #2 }
}
\NewDocumentCommand{\appendtolist}{mm}
{
\clist_put_right:cn { l_lennart_list_#1_clist } { #2 }
}
\NewExpandableDocumentCommand{\listlength}{m}
{
\clist_count:c { l_lennart_list_#1_clist }
}
\NewExpandableDocumentCommand{\branchonlist}{mmm}
{% #1 = list name, #2 = cases, #3 = no match
\int_case:nnF { \clist_count:c { l_lennart_list_#1_clist } } { #2 } { #3 }
}
\ExplSyntaxOff
\definelist{fruits}{apple,mango,banana}
\definelist{animals}{gnu,gnat}
\definelist{letters}{a}
\begin{document}
Number of fruits: \listlength{fruits}
\branchonlist{fruits}{
{1}{There is just a single fruit}
}{There are multiple fruits}
\bigskip
Number of animals: \listlength{animals}
\branchonlist{animals}{
{1}{There is just a single animal}
{2}{There are two animals}
}{There are multiple animals}
\bigskip
Number of letters: \listlength{letters}
\branchonlist{letters}{
{1}{There is just a single letter}
{2}{There are two letters}
{3}{There are three letters}
}{There are multiple letters}
\bigskip
\appendtolist{letters}{b}
Number of letters: \listlength{letters}
\branchonlist{letters}{
{1}{There is just a single letter}
{2}{There are two letters}
{3}{There are three letters}
}{There are multiple letters}
\bigskip
\appendtolist{letters}{c}
Number of letters: \listlength{letters}
\branchonlist{letters}{
{1}{There is just a single letter}
{2}{There are two letters}
{3}{There are three letters}
}{There are multiple letters}
\bigskip
\appendtolist{letters}{d}
Number of letters: \listlength{letters}
\branchonlist{letters}{
{1}{There is just a single letter}
{2}{There are two letters}
{3}{There are three letters}
}{There are multiple letters}
\end{document}