Как использовать структуры данных в TikZ?

Как использовать структуры данных в TikZ?

Я создал оператор foreach, используяexpl3иTikZ/pgf:

\documentclass{article}
\usepackage{tikz}
\setlength{\parindent}{0cm}
\usepackage{expl3}
\ExplSyntaxOn
\cs_new:Npn \Counter #1 \Stopper { \tl_length:n {#1} }
\ExplSyntaxOff
\pgfmathdeclarefunction{countarray}{1}{\edef\pgfmathresult{\Counter#1\Stopper}}
\begin{document}
%array with names
\def\names{{"Katie","Frank","Laura"}}

%find the last element index
\pgfmathtruncatemacro{\Last}{countarray(\names) - 1}

%print all the elements of array
\foreach \i in {0,...,\Last} {%
  \i: \pgfmathparse{\names[\i]}\pgfmathresult\\
}
\end{document}

Печатает это:

введите описание изображения здесь

Предположим, я хочу использовать разные цвета для разных имен (или задать какие-то другие параметры). Получаем что-то вроде этого:

Katie\\
\textcolor{blue}{Frank}\\
Laura

введите описание изображения здесь

На Perl я бы сделал что-то вроде этого:

my @data = (
  {"text" => "Katie"},
  {"text" => "Frank", "color" => "blue"},
  {"text" => "Laura"});

foreach(@data)
{
      if(defined($_->{color}))
      {
            print "\textcolor\{$_->{color}\}\{$_->{text}\}";
      }
      else
      {
            print $_->{text};
      }
      print "\\\\";
}

Возможно ли реализовать это в expl3?

решение1

Я не знаю, expl3но это возможно в TikZ, или, скорее, в pgfkeys. Поскольку есть l3keysподмодуль LaTeX3, я предполагаю, что в принципе та же идея работает и там. Вы можете создать свою структуру данных примерно так же, как в Perl:

\pgfkeys{
 /names/.cd,
 make name/.style = {
  #1/color/.initial = black
 },
 make name/.list = {Katie, Frank, Laura},
 Frank/color = blue
}

Затем вы можете извлечь цвет имени, например, с помощью:

\newcommand\getcolor[1]{%
 \pgfkeysgetvalue{/names/#1/color}%
}

который полностью расширяем и может использоваться везде, где вам нужен цвет имени. Конечно, для этого примера нет необходимости в одном подключе Frank/color(вы можете просто задать Frank/.initial = blue), но если вам нужно больше свойств, вы можете добавить их, дав им также их собственные именованные подключи.

решение2

Это в конечном итоге не дает ответа на вопрос:

Возможно ли реализовать это в expl3?

поэтому он отмечен как сообщество вики.

Помимо интересного аспекта работы с expl3, эта работа прекрасно выполнима с помощью стандартного синтаксиса TikZ foreach в сочетании сxstring:

\documentclass{article}
\usepackage{tikz} % won't work just with pgffor
\setlength{\parindent}{0cm}
\usepackage{xstring}
\begin{document}

\foreach \name [count=\i from 0]in{Katie,Frank=>blue,Laura=>red}{
   \IfSubStr{\name}{=>}{% true
     \StrCut{\name}{=>}\xname\namecol
     \i: \textcolor{\namecol}{\xname}\par%
   }{% false
     \i: \name\par%
   }
}

\end{document}

Это обеспечивает:

введите описание изображения здесь

Идея примерно такая:

  1. найдите разделительную строку ( =>в примере);
  2. если есть, разрежьте строку на две части (название и цвет) и используйте их;
  3. если отсутствует, используйте стандартный синтаксис.

Конечно, возможно:

  • изменить строку разделителя;
  • выполнять гораздо более сложные задачи (например, добавлять больше свойств: просто вкладывать некоторые условные операторы или, проще говоря, определять одну строку-разделитель для каждого свойства).

решение3

Предположим, мы хотим, чтобы наш код поддерживал 2 свойства текста: цвет и курсив. Сначала мы определяем plists:

%plist1 definition
\prop_new:N \l_list_a_prop
\prop_put:Nnn \l_list_a_prop { text } {Katie}

%plist2 definition
\prop_new:N \l_list_b_prop
\prop_put:Nnn \l_list_b_prop { text } {Frank}
\prop_put:Nnn \l_list_b_prop { color } {red}

%plist3 definition
\prop_new:N \l_list_c_prop
\prop_put:Nnn \l_list_c_prop { text } {Laura}
\prop_put:Nnn \l_list_c_prop { color } {blue}
\prop_put:Nnn \l_list_c_prop { italic } {yes}

Обратите внимание, что expl3 не поддерживает цифры в именах, поэтому я использовал _a, _b, _c.

Затем объедините все листы в последовательность:

%putting plists to sequence
\seq_new:N \l_my_seq
\seq_push:Nn \l_my_seq { \l_list_c_prop }
\seq_push:Nn \l_my_seq { \l_list_b_prop }
\seq_push:Nn \l_my_seq { \l_list_a_prop }

Затем мы проходим по последовательности и при необходимости добавляем в текст соответствующую разметку:

\tl_new:N \__text
\seq_map_inline:Nn \l_my_seq
{
  \prop_get:NnN #1 { text } \__text

  \prop_get:NnNT #1 { color } \color_tl
  {
    \protected@edef \__text {\textcolor{\color_tl}{\__text}}
  }

  \prop_get:NnNT #1 { italic } \italic_tl
  {
    \protected@edef \__text {\textit{\__text}}
  }

  \__text\\
}

В целом у нас есть следующий код:

\documentclass{article}
\usepackage{expl3}
\usepackage{color}
\setlength\parindent{0pt}
\begin{document}
\makeatletter
\ExplSyntaxOn

%plist1 definition
\prop_new:N \l_list_a_prop
\prop_put:Nnn \l_list_a_prop { text } {Katie}

%plist2 definition
\prop_new:N \l_list_b_prop
\prop_put:Nnn \l_list_b_prop { text } {Frank}
\prop_put:Nnn \l_list_b_prop { color } {red}

%plist3 definition
\prop_new:N \l_list_c_prop
\prop_put:Nnn \l_list_c_prop { text } {Laura}
\prop_put:Nnn \l_list_c_prop { color } {blue}
\prop_put:Nnn \l_list_c_prop { italic } {yes}

%putting plists to sequence
\seq_new:N \l_my_seq
\seq_push:Nn \l_my_seq { \l_list_c_prop }
\seq_push:Nn \l_my_seq { \l_list_b_prop }
\seq_push:Nn \l_my_seq { \l_list_a_prop }

\tl_new:N \__text
\seq_map_inline:Nn \l_my_seq
{
  \prop_get:NnN #1 { text } \__text

  \prop_get:NnNT #1 { color } \color_tl
  {
    \protected@edef \__text {\textcolor{\color_tl}{\__text}}
  }

  \prop_get:NnNT #1 { italic } \italic_tl
  {
    \protected@edef \__text {\textit{\__text}}
  }

  \__text\\
}
\ExplSyntaxOff
\makeatother
\end{document}

Это напечатает:

введите описание изображения здесь

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