Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.
\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?

share|improve this question
    
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\Pe‌​rsonList\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. –  jfbu Nov 15 '13 at 20:11
add comment

3 Answers

up vote 4 down vote accepted

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}
share|improve this answer
add comment

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

share|improve this answer
add comment

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

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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