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.

I've got a large multi-purpose database and i would like to pick several items in it (using labels) and print them in the given order, not the database order or any entry-related order.

For example, i currently use this code (found on this site, thanks to Peter Grill) :

\documentclass{article}  
\usepackage{datatool}
\usepackage{longdata}

\usepackage{filecontents}
\begin{filecontents*}{foo.dat}
Hammer001,   Hammer,    1 ,  0 , 1 , 10 , 1 , light\\
Hammer002,   Hammer,    2 ,  0 , 1 , 10 , 1 , heavy\\
Hammer003,   Hammer,    3 ,  0 , 1 , 10 , 1 , really heavy\\
Longsword001,Longsword, 1 , -1 , 2 , 75 , 2 , one-handed \\
Longsword002,Longsword, 2 , -1 , 2 , 75 , 2 , two-handed \\
Longsword003,Longsword, 3 , -1 , 2 , 75 , 2 , three-handed \\
\end{filecontents*}

\newcommand{\PrintDTLTable}[2]{%
% #1 = database to search
% #2 = list of rowIDs
\begin{enumerate}
\DTLforeach*[\DTLisSubString{#2}{\RowID}]{#1}{%
    \RowID=RowID,%
    \Label=Label,%
    \Cost=Cost,%
    \Weight=Weight,%
    \Description=Description%
    }{%
    \item \Label ; Price=\Cost ; Weight=\Weight ; It's very \Description
}%
\end{enumerate}
}%

\begin{document}

\DTLloaddb[noheader,keys={RowID,Label,Cost,Weight,PropA,PropB,PropC,Description}]{myDB}{foo.dat}

\PrintDTLTable{myDB}{Hammer001,Hammer003,Longsword003}
\end{document}

The command

\PrintDTLTable{myDB}{Hammer001,Hammer003,Longsword003}

is doing exactly what i want except that

\PrintDTLTable{myDB}{Hammer003,Longsword003,Hammer001}

would obviously produce the exact same result.

Is there any way to keep the given order ? (sorry for my poor english)

share|improve this question

1 Answer 1

up vote 9 down vote accepted

\DTLforeach visits the rows one after another. Therefore the row order of the data base matters:

\DTLforeach*[\DTLisSubString{#2}{\RowID}]{#1}{%
 % #2 = list of rowIDs

In the following solution I have put the data extraction in a for loop that iterates over the given row IDs. There are many for loops, e.g. LaTeX's \@for. I am using \comma@parse from package kvsetkeys, because it removes leading and trailing spaces from the entries in the list. Then the row id is compared with \equal to get only exact matches.

\usepackage{kvsetkeys}

\makeatletter
\newcommand{\PrintDTLTable}[2]{%
  % #1 = database to search
  % #2 = list of rowIDs
  \begin{enumerate}
    \comma@parse{#2}{%
      \DTLforeach*[\equal{\comma@entry}{\RowID}]{#1}{%
        \RowID=RowID,%
        \Label=Label,%
        \Cost=Cost,%
        \Weight=Weight,%
        \Description=Description%
      }{%
        \item \Label ; Price=\Cost ; Weight=\Weight ; It's very \Description
        \dtlbreak
      }%
      \@gobble % ignore the entry argument provided by \comma@parse
    }%
  \end{enumerate}
}%
\makeatother

Of course the run time behaviour of this algorithm is poor. For a data base with n entries and m selected rows is is is O(n*m). That means O(n²) if the whole data base is output. Theoretically sorting can be done in O(n*log(n)).

share|improve this answer
    
<sup>2</sup> works on tex.sx as well (and so does <sub>...</sub>). –  doncherry Jul 27 '12 at 14:50

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.