4

I’m defining datas in LaTeX with a custom command that stores both a label and a number:

\documentclass{article}
\usepackage{parskip}

\newcommand{\data}[3]{%
  \expandafter\newcommand\csname #1\endcsname[1][]{#2##1}%
  \expandafter\newcommand\csname #1Number\endcsname{#3}%
}

\newcommand{\getnumber}[1]{%
  \mbox{\textbf{(\csname #1Number\endcsname)}}%
}

\begin{document}

% Vegyületek
\data{tempA}{aaa}{1}
\data{tempB}{bbb}{2}
\data{tempC}{ccc}{3}
\data{tempD}{ddd}{4}
\data{tempE}{eee}{5}
\data{tempF}{fff}{6}

Data: \tempA \newline
Number: \getnumber{tempA}

\end{document}

For a single compound, \getnumber{tempA} outputs (1).

Now I want to create a command that takes a list of compound names and outputs a range summary of their numbers. For example:

\getnumberrange{tempA,tempB,tempC,tempF}  % should produce (1-3,6)

I’m not sure how to iterate over a list of command names, retrieve their numbers, and compress consecutive numbers into ranges. How can I implement this in LaTeX?

4
  • 1
    You could consider to store them into a l3clist, that is(is automatically rearrange the order) \getnumberrange{tempA,tempC,tempB,tempF} to a clist: 1,3,2,6, and be sorted 1,2,3,6, and use loops to judge whether the next item(clist[i+1]) of clist[i] is clist[i]+1, and replace them with -. But I was not sure what is the exact use of this command, it looks like duplicated wheels in cleveref or zref-clever or cite package.... Commented 12 hours ago
  • 1
    is there a reason not to use latex's standard \label/\ref system here? as @Explorer said, then you could use e.g. zref-clever which can compress and format ranges etc. in addition to this, I think it would help if you could say a bit more about the end goal here. Commented 12 hours ago
  • This quesion is the opposite/dual one of this: tex.stackexchange.com/q/494712/322482 Commented 8 hours ago
  • Mandatory read for this: lambda-lists (documentation of lambda.sty) Commented 5 hours ago

1 Answer 1

4

Based on my comment, I give an expl3 attempt:

\documentclass{article}
\newcommand{\data}[3]{%
  \expandafter\newcommand\csname#1\endcsname[1][]{#2##1}%
  \expandafter\newcommand\csname#1Number\endcsname{#3}%
}
\ExplSyntaxOn
\cs_new:Npn \__taiwan_getnum:n #1
{
    \cs:w#1Number\cs_end:
}
\newcommand{\getnumber}[1]{%
%   \mbox{\textbf{(\__taiwan_getnum:n {#1})}}%
    \__taiwan_getnum:n {#1}%
}
\clist_new:N \l__taiwan_numrange_clist
\clist_new:N \l__taiwan_num_clist
\tl_new:N \l__taiwan_tmp_tl
\int_new:N \l__taiwan_tmp_int
\int_new:N \l__taiwan_start_int
\cs_new:Npn \__taiwan_getnumrange:n #1
{
    \group_begin:
    \clist_set:Nn \l__taiwan_numrange_clist {#1}
    \clist_clear:N \l__taiwan_num_clist
    \clist_map_inline:Nn \l__taiwan_numrange_clist
    {
        \clist_put_right:Nn \l__taiwan_num_clist {\__taiwan_getnum:n {##1}}%
    }
    \clist_sort:Nn \l__taiwan_num_clist
    {
        \int_compare:nNnTF { ##1 } > { ##2 }
        { \sort_return_swapped: }
        { \sort_return_same: }
    }
    \clist_pop:NN \l__taiwan_num_clist \l__taiwan_tmp_tl
    \int_set:Nn \l__taiwan_tmp_int { \l__taiwan_tmp_tl }
    \int_set:Nn \l__taiwan_start_int { \l__taiwan_tmp_tl }
    \clist_map_inline:Nn \l__taiwan_num_clist
    {
        \int_compare:nNnTF { ##1 } = { \int_eval:n { \l__taiwan_tmp_int + 1 } }
        {
            % consecutive
            \int_set:Nn \l__taiwan_tmp_int { ##1 }
        }
        {
            % not consecutive
            \int_compare:nNnTF { \l__taiwan_start_int } = { \l__taiwan_tmp_int }
            {
                % single number
                ~\int_use:N \l__taiwan_start_int ,
            }
            {
                % range
                ~ \int_use:N \l__taiwan_start_int -- \int_use:N \l__taiwan_tmp_int ,
            }
            \int_set:Nn \l__taiwan_start_int { ##1 }
            \int_set:Nn \l__taiwan_tmp_int { ##1 }
        }
    }
    \int_compare:nNnTF { \l__taiwan_start_int } = { \l__taiwan_tmp_int }
    {
        ~\int_use:N \l__taiwan_start_int
    }
    {
        ~ \int_use:N \l__taiwan_start_int -- \int_use:N \l__taiwan_tmp_int
    }
    \group_end:
}
\newcommand{\getnumberrange}[1]{%
    \__taiwan_getnumrange:n {#1}
}
\ExplSyntaxOff

\begin{document}

\data{tempA}{aaa}{1}
\data{tempB}{bbb}{2}
\data{tempC}{ccc}{3}
\data{tempD}{ddd}{4}
\data{tempE}{eee}{5}
\data{tempF}{fff}{6}

Data: \tempA 

Number: \getnumber{tempA} and \getnumber{tempD} 

Number Range: \getnumberrange{tempA,tempE,tempF,tempC}

Number Range: \getnumberrange{tempA,tempC,tempE}

Number Range: \getnumberrange{tempD,tempC}

Number Range: \getnumberrange{tempA,tempE,tempF,tempC,tempB,tempD}

Number Range: \getnumberrange{tempA,tempE,tempF,tempB,tempD}

\end{document}

result

Noted that I don't think I did a good job, as cfr also mentioned at here, there are similar achievement in zref-clever or cite to privide similar option named sort&compress, the above is probably reinvent-ing the wheels(NO!), so just regard it as my latex3 exercise. As for the () outside the outcome, you can add it on your own.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.