Как присвоить значения с помощью foreach?

Как присвоить значения с помощью foreach?

У меня возникли проблемы с присвоением значений с помощью \foreach. Может кто-нибудь мне помочь? Следующий код неверен. Цель — присвоение значений: \lx1=1, \ly1=2, \lz1=3, например.

\foreach \x/\y in {\lx1/1,\ly1/2,\lz1/3}
{%
\def\x{\y}
\x{\y}
{

решение1

Есть несколько причин, почему это не работает:

  • \lx1не является именем команды, оно состоит из команды \lx, за которой следует цифра 1. Либо замените 1буквой, либо использование будет немного сложнее с помощью \csname.

  • \xи \yсодержат значения x и y, определение \xdefines \x, а не макрос внутри и \yбудет изменяться с каждым циклом. \expandafterрасширяет макрос на один уровень:

    \expandafter\def\x{...}
    

    Для выполнения того же самого \yтребуется гораздо больше \expandafter, поэтому \let здесь проще использовать .

  • \foreachпомещает тело цикла внутрь групп, таким образом локальные определения будут потеряны. Это можно решить с помощью глобальных определений.

Пример:

\usepackage{pgffor}

\foreach \x/\y in {\lxA/1,\lyA/2,\lzA/3}
{%
  \global\expandafter\let\x\y
}

Или с помощью \lx1макроса:

\foreach \x/\y in {\lx1/1,\ly1/2,\lz1/3}
{%
  \begingroup
    \escapechar=-1 % suppresses backslash with \string
    \global\expandafter\let
    \csname \expandafter\string\x\endcsname\y
  \endgroup
}

\typeout{\expandafter\string\csname lx1\endcsname:
  \expandafter\meaning\csname lx1\endcsname}

Дополнение для фанатов \expandafter:

\gdefможно использовать вместо \global\letс помощью дополнительных \expandafter:

\foreach \x/\y in {\lxA/1,\lyA/2,\lzA/3}
{%
  \expandafter\expandafter\expandafter
  \gdef\expandafter\x\expandafter{\y}%
}

\typeout{\string\lxA: \meaning\lxA}

\foreach \x/\y in {\lx1/1,\ly1/2,\lz1/3}
{%
  \begingroup
    \escapechar=-1 % suppresses backslash with \string
    \expandafter\gdef
    \csname \expandafter\string\x\expandafter\endcsname
    \expandafter{\y}%
  \endgroup
}

\typeout{\expandafter\string\csname lx1\endcsname:
  \expandafter\meaning\csname lx1\endcsname}

Как видно, версия с \letболее эффективна и элегантна.

Связанный контент