6

Apologies for an unclear title; I'm not sure how to describe what it is I want to do (please feel free to edit my tags). But here is my best shot:

I have a collection of data; each datum is an ordered pair of text. Let's suppose that for each datum, I can make a corresponding macro that "knows" both its pieces of text. I don't know how such a macro would work, but let's say that the macro \mynumber represents (six,two) and \mycolor represents (blue,red).

What I'd like is a macro \arrange such that compiling

Lorem ipsum \mynumber, dolor sit amet \mycolor, etc...

\arrange

produces

Lorem ipsum six, dolor sit amet blue, etc...

two, red

The key property I am looking for is that \arrange presents the second entries in the order that the data were mentioned in the text above. That is, if I edit the first part of my document so that \mycolor occurs before \mynumber, I want two and red to switch positions below.

What I hope to avoid is having to separately specify the order I will mention the data in the first part of my text, and then passing it to \arrange; the whole point is that I want to be able to edit the first part of my document carefree, and have the second entries of my data appear below in the right order, without having to painstakingly reorder anything elsewhere in the document by hand.

The greater the versatility of the output formatting of \arrange, the better - e.g., if I change my mind and want \arrange to put its results on separate lines instead of being separated by commas, I'd like that to be possible.

3 Answers 3

6

You need to re-arrange the data in a meaningful way. What you are describing are tuples that are simply key value pairs, for example

two=red
six=blue

A simple way to handle them, is to enter this information using macros:

\newcommand\two{red}
\newcomand\six{blue}

However, this might be a bit difficult to enter and one may way to automate it, so let us assume that the macros one, two, three etc are colors we can then save them in a comma delimited list:

\colorlist{one,two,three,four,five,six}

and the colors as a \colorlistvalues{green,blue,yellow,orange,purple,red},

We can then iterate over the two lists automatically to create the macros \one,\two etc. automatically or create a utility to add the key value pairs. The latter is more flexible and semantically correct:

 \addacolor{one}{red}
 \addacolor{two}{blue}
 \addacolor{three}{purple}

And here is the full minimal:

\documentclass{article}
\makeatletter

\def\colorlist{}
\def\colorlistvalues{}

\def\addacolor#1#2{%
\g@addto@macro\colorlist{#1,}
\g@addto@macro\colorlistvalues{#2,}
\expandafter\def\csname#1\endcsname{#2}
}
\makeatother
\begin{document}

\addacolor{one}{red}
\addacolor{two}{blue}
\addacolor{three}{purple}


\one,\two

\colorlist

\colorlistvalues
\end{document}

See also how to set properties https://tex.stackexchange.com/a/37096/963, which is very similar to what you want, as well as Adding a list of bios to the book class.

2

The following does what you're looking for by building up a list (\arrangement) as you call \mynumber and/or \mycolor. So, regardless of the order in which you call them, the list is built up in that order.

enter image description here

\documentclass{article}
\makeatletter
\def\storenumber(#1,#2){%
  \def\mynumber@one{#1}% Store first argument
  \def\mynumber@two{#2}% Store second argument
}
\def\storecolor(#1,#2){%
  \def\mycolor@one{#1}% Store first argument
  \def\mycolor@two{#2}% Store second argument
}
\let\arrangement\relax% Empty arrangement
\def\mynumber{%
  \mynumber@one% Set first number
  \setbox0=\hbox{\arrangement}%
  \ifdim\wd0=0pt % Check if \arrangement already has an item
    \edef\arrangement{\mynumber@two}%
  \else % \arrangement DOES have an item
    \edef\arrangement{\arrangement, \mynumber@two}%
  \fi%
}
\def\mycolor{%
  \mycolor@one% Set first colour
  \setbox0=\hbox{\arrangement}%
  \ifdim\wd0=0pt % Check if \arrangement already has an item
    \edef\arrangement{\mycolor@two}%
  \else % \arrangement DOES have an item
    \edef\arrangement{\arrangement, \mycolor@two}%
  \fi%
}
\def\arrange{%
  \arrangement% Set \arrangement
  \let\arrangement\relax% Clear/erase arrangement
}
\makeatother
\begin{document}

% Setup number/colour
\storenumber(six,two) \storecolor(blue,red)

Lorem ipsum \mynumber, dolor sit amet \mycolor, etc\ldots

\arrange % Print \arrangement

Lorem ipsum \mycolor, dolor sit amet \mynumber, etc\ldots

\arrange % Print \arrangement

\end{document}

The macros \storenumber(<one>,<two>) and \storecolor(<one>,<two>) set up the two pairs of data points. \mynumber and \mycolor each set the first of their pairs, while also checking to see how it should add to a macro called \arrangement (either it would be a first or a following item). \arrange sets the constructed/ordered arrangement of second item pairs.

2
\documentclass[a4paper]{article}

\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\newpair}{ m m m }
  {
   \cs_new_protected:Npn #1 { \zevc_print_and_add:nn { #2 } { #3 } }
  }
\cs_new:Npn \zevc_print_and_add:nn #1 #2
  {
   #1 % print the first element
   \cs_if_exist:cF { zevc_ \tl_to_str:n { #1 + #2 } _tl } % store the second element
     {
      \seq_gput_right:Nn \g_zevc_keys_seq { #2 }
      \tl_new:c { zevc_ \tl_to_str:n { #1 + #2 } _tl } % only once
     }
  }
\seq_new:N \g_zevc_keys_seq
\NewDocumentCommand{\arrange}{ }
  {
   \seq_gpop_right:NN \g_zevc_keys_seq \l_tmpa_tl % detach the last element
   \seq_map_inline:Nn \g_zevc_keys_seq { ##1,~ } \tl_use:N \l_tmpa_tl
   \seq_gput_right:NV \g_zevc_keys_seq \l_tmpa_tl % restore for possible future use
  }
\ExplSyntaxOff

\newpair{\mycolor}{blue}{red}
\newpair{\mynumber}{six}{two}

\begin{document}

Lorem ipsum \mynumber, dolor sit amet \mycolor, etc...

\arrange

\end{document}

The \newpair command defines the macros: it takes as argument the name, the first value and the second value:

\newpair{\mynumber}{six}{two}

When you use \mynumber, then "six" is printed and "two" is added to the sequence \g_zevc_keys_seq, but only if it hasn't been added before. To check this we set a new token list variable, whose name is composed by zev_c, six+two and _tl so as to ensure uniqueness (we are assuming that the ordered pairs are all distinct). Of course this is not necessary if you want to later print all the second elements, irrespectively of duplicates.

The \arrange command just prints in sequence all the items progressively added so far. In order to print them separated by commas, we detach the last element, print all the remaining followed by a comma and a space, then print the last element. Then we restore the sequence, for possible future uses. The order will be that of appearance in the text.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .