6
\documentclass[preview,border=12pt,varwidth]{standalone}
\usepackage{pgffor}

\def\Person#1{%
    \ifcsname#1\endcsname
    \else 
        \expandafter\def\csname #1\endcsname{#1}%
    \fi
        \csname#1\endcsname
}

\begin{document}
\Person{Alan} took  a shower when 
\Person{Batman} was cooking in the 
\Person{Carlisle}'s house which lies  3 meter due east of
\Person{David}'s school or 4 meter due west of
\Person{Enrico}'s office.

How can I iterate through the persons mentioned in the first paragraph?
\end{document}

enter image description here

How to iterate through all user-defined control-words without using \foreach macro and listing the names manually?

  • Save them in a list. – Marco Daniel Nov 15 '13 at 15:27
  • follow-up on Marco's comment: e.g. add \expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter\PersonList\expandafter\expandafter\expandafter{\expandafter\PersonList\expandafter{\csname #1\endcsname}} to your \else clause and \let\PersonList\empty before the defintion of \Person. Then \PersonList will expand to {\Alan }{\Batman }{\Carlisle }{\David }{\Enrico }. You can use any utility able to do things with this (I put the braces because this utility might want to expand \PersonList first, and braces will stop it from expanding \Alan as well too early. – user4686 Nov 15 '13 at 20:11
4

Any list-processing package should be able to handle this. I'm most familiar with etoolbox, althought LaTeX3 has some easy-to-use functionality as well.

enter image description here

\documentclass{article}
\usepackage{etoolbox}% http://ctan.org/pkg/etoolbox

\newcommand{\PersonList}{}% Declare list
\newcommand{\Person}[1]{%
  \ifinlist{#1}{\PersonList}% \ifinlist{<item>}{<list>}
    {}% <true>
    {\listgadd{\PersonList}{#1}}% <false>
    #1% Print Person
}
\newcommand{\PrintPersons}{% Whatever you want to do with the list...
  \def\insertgap{\def\insertgap{ }}% http://tex.stackexchange.com/a/89187/5764
  \forlistloop{\insertgap}{\PersonList}}% Process list

\begin{document}
\Person{Alan} took  a shower when \par
\Person{Batman} was cooking in the \par
\Person{Carlisle}'s house which lies  3 meter due east of \par
\Person{David}'s school or 4 meter due west of \par
\Person{Enrico}'s office.

How can I iterate through the persons mentioned in the first paragraph? \par
\PrintPersons
\end{document}
| improve this answer | |
5

Plain TeX, just for a change (no e-TeX).

\def\PersonList{}
\def\Person#1{%
  \expandafter\ifx\csname#1@Listed\endcsname\relax
    \expandafter\let\csname#1@Listed\endcsname\empty
    \expandafter\def\expandafter\PersonList\expandafter{\PersonList\doPerson{#1}}%
  \fi
  #1%
}

\def\doPerson#1{#1 was listed\par}

\Person{Alan} took  a shower when
\Person{Batman} was cooking in the
\Person{Carlisle}'s house which lies  3 meter due east of
\Person{David}'s school or 4 meter due west of
\Person{Enrico}'s office.

\bigskip

\PersonList

\bye

enter image description here

And now a LaTeX3 version where \PersonList takes an optional argument for the function to execute for each person listed.

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\Person}{m}
 {
  \egreg_addperson:n { #1 }
 }
\NewDocumentCommand{\PersonList}{O{\doPersonDefault}}
 {
  \egreg_listpersons:N #1
 }
\NewDocumentCommand{\doPersonDefault}{m}
 {
  #1~was~listed\par
 }

\seq_new:N \g_egreg_persons_seq

\cs_new_protected:Npn \egreg_addperson:n #1
 {
  \seq_if_in:NnF \g_egreg_persons_seq { #1 }
   {
    \seq_gput_right:Nn \g_egreg_persons_seq { #1 }
   }
  #1
 }

\cs_new_protected:Npn \egreg_listpersons:N #1
 {
  \seq_map_function:NN \g_egreg_persons_seq #1
 }
\ExplSyntaxOff

\newcommand{\doPerson}[1]{Yes, #1 was listed, what else?\par}

\begin{document}

\Person{Alan} took  a shower when 
\Person{Batman} was cooking in the 
\Person{Carlisle}'s house which lies  3 meter due east of
\Person{David}'s school or 4 meter due west of
\Person{Enrico}'s office.

\bigskip

\PersonList

\bigskip

\PersonList[\doPerson]

\end{document}

enter image description here

| improve this answer | |
2

From my comment based on Marco Daniel's comment, but I am not sure I understood the question correctly.

\documentclass[preview,border=12pt,varwidth]{standalone}
\usepackage{pgffor}

\let\PersonList\empty
\def\Person#1{%
    \ifcsname#1\endcsname
    \else 
        \expandafter\expandafter\expandafter\def
        \expandafter\expandafter\expandafter\PersonList
        \expandafter\expandafter\expandafter
              {\expandafter\PersonList\expandafter{\csname #1\endcsname}}%
        \expandafter\def\csname #1\endcsname{#1}%
    \fi
        \csname#1\endcsname
}

\begin{document}
\Person{Alan} took  a shower when 
\Person{Batman} was cooking in the 
\Person{Carlisle}'s house which lies  3 meter due east of
\Person{David}'s school or 4 meter due west of
\Person{Enrico}'s office.

How can I iterate through the persons mentioned in the first paragraph?
\texttt{\meaning\PersonList}
\end{document}

nameiteration

| improve this answer | |

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.