2

This topic is following my previous question, which was marvelously answered by BambOo yesterday.

Now for a step beyond into this project.

Let's admit I want to put a list of letters (or words) on a 6 columns grid and stylize them depending on their content.

In the following example, I displayed a simple alphabet, and a [count=\i] into the loop, but I'd like to be able to compare directly the node content, i.e. something like ifthenelse(\l<"J", nodeone, nodetwo). Is there any simple way to do that?

\documentclass[a4paper, 11pt]{article}

\usepackage[utf8]{inputenc}
\usepackage[french]{babel}
\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage{tikz}
\usetikzlibrary{shapes}

\usepackage{ifthen}


\begin{document}


\begin{center}
\begin{tikzpicture}


\tikzstyle{nodeone}=[circle, fill=cyan!50!yellow,text=purple,opacity=1,minimum height=30]
\tikzstyle{nodetwo}=[regular polygon,regular polygon sides=5, fill=orange!50!red,text=cyan,opacity=1,minimum height=30]
\tikzstyle{nodethree}=[star,star points=7,star point ratio=0.8, fill=red!50!blue,text=orange,opacity=1,minimum height=30]



\def\LX{2} \def\LY{3} \def\ncol{6} % dimensions of the grid
\def\firstlim{8} \def\secondlim{17}

\foreach \l [count=\i from 0] in {A,...,Z}
    {
    \pgfmathsetmacro{\nodestyl}
        {
        ifthenelse(\i<\firstlim,"nodeone",
            ifthenelse(\i<\secondlim,"nodetwo","nodethree")
        }%

    \pgfmathtruncatemacro\result{\i/\ncol}
    \node[\nodestyl] at ({Mod(\i,\ncol)*\LX},-\result*\LY) {\sf \Large \textbf{\l}};
    }


\end{tikzpicture}
\end{center}

\end{document}

The 6 column grid

I already looked into etoolbox to find something that could help, and I found a way to test if strings are equal : \expandafter\ifstrequal\expandafter{\l}{A}{\nodeone}{nodetwo}, but not yet a way to test if string1 is inferior to string2.

1 Answer 1

4

You can do such comparisons with \pdf@strcmp from the pdftexcmds package. I've tested the following code with pdfTeX, XeTeX and LuaTeX—all of these support the command. \pdf@strcmp expands to -1, 0 or 1 depending on whether the first string compares strictly less, equal to or strictly greater than the second string (ASCII is certainly supported; for the rest, I don't know—this might be engine-dependent).

Don't use \tikzstyle, it is obsolete; instead, use \tikzset or the optional argument of tikzpicture (see below). Prefer using the font option to define the font to be used in TikZ nodes and never use \sf with LaTeX: it is a plain TeX font command, not LaTeX. Better use \sffamily or \textsf—these are LaTeX font selection commands.

\documentclass[tikz, border=1mm]{standalone}
\usetikzlibrary{shapes}
\usepackage{pdftexcmds}

\makeatletter
% Expand #1 once before comparing it to #2
\newcommand*{\mystrcmp}[2]{%
  \expandafter\pdf@strcmp\expandafter{#1}{#2}%
}
\makeatother

\begin{document}
\begin{tikzpicture}[
  nodeone/.style={circle, fill=cyan!50!yellow,text=purple,opacity=1,
                  minimum height=30},
  nodetwo/.style={regular polygon,regular polygon sides=5,
                  fill=orange!50!red,text=cyan,opacity=1,minimum height=30},
  nodethree/.style={star,star points=7,star point ratio=0.8,
                    fill=red!50!blue,text=orange,opacity=1,minimum height=30},
  ]

% Dimensions of the grid
\newcommand*{\LX}{2} \newcommand*{\LY}{3} \newcommand*{\ncol}{6}

\foreach \l [count=\i from 0] in {A,...,Z}
  {
    \edef\myNodestyle{%
      \ifnum\mystrcmp{\l}{I}=-1   % space intended
        nodeone%
      \else
        \ifnum\mystrcmp{\l}{R}=-1 % space intended
          nodetwo%
        \else
          nodethree%
        \fi
      \fi
    }

    \pgfmathtruncatemacro{\result}{\i/\ncol}
    \node[\myNodestyle, font=\sffamily\Large\bfseries]
      at ({Mod(\i,\ncol)*\LX}, -\result*\LY) {\l};
  }
\end{tikzpicture}
\end{document}

enter image description here

7
  • Wonderful, thanks a lot, frougon! I'm not familiar with this "expansion"system, I read a lot about it and still don't figure exactly what it means. Another subject I might learn about. I'm on a strict "user level" with LaTeX, not yet able to dig into the real coding. Anyway, your solution is plain and simple to understand and to use.
    – SebGlav
    Apr 27, 2020 at 15:49
  • An improvement I'd like to add to this is to be able to compare the argument to a predefined list of words. All these little things that are so easy in python or any coding language and that are very hard to achieve in LaTeX (which is not really made for, I have to admit).
    – SebGlav
    Apr 27, 2020 at 15:55
  • 1) On expansion. Short answer: read the TeXbook (if you have time and want to understand, I'm serious!). There are two very important mechanisms in TeX: expansion replaces tokens by other tokens; execution performs “other things” such as adding a box or glue item to the current horizontal, vertical or math list, shiping out a new page, etc. These are very different. Expansion is what replaces a macro by its definition, but not only: \the and \string are not macros (they are primitives) but they expand to other tokens. Expansion occurs recursively in several contexts. One of these ...
    – frougon
    Apr 27, 2020 at 16:03
  • ... is when TeX is reading a 〈number〉. This is the case on either side of the comparison operator when using \ifnum, and that's what we rely on in \mystrcmp. \expandafter triggers one expansion step after skipping over the next token. It doesn't trigger execution. Execution happens when unexpandable tokens such as \hbox or \def, or \edef, etc. reach TeX's stomach. 2) On string manipulation. LaTeX doesn't deal with “strings” like Python. It deals with token lists. A character token not only has a charcode but also a catcode. This is like a second dimension.
    – frougon
    Apr 27, 2020 at 16:13
  • 1
    Thanks a lot for this comprehensive answer. A lot to learn, indeed. Very nice from you to offer your help. I'm grateful.
    – SebGlav
    Apr 29, 2020 at 14:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.