% !TeX TXS-program:compile = txs:///arara % arara: pdflatex: {shell: no, synctex: no, interaction: batchmode} % arara: pdflatex: {shell: no, synctex: no, interaction: batchmode} \documentclass[11pt,a4paper]{ltxdoc} \usepackage{bera} \usepackage{inconsolata} \usepackage[T1]{fontenc} \usepackage[scale=0.875]{cabin} \usepackage{commalists-tools-l3} \usepackage{listofitems} \usepackage{fancyvrb} \usepackage{fancyhdr} \usepackage{tabularray} \usepackage{fontawesome5} \fancyhf{} \renewcommand{\headrulewidth}{0pt} \lfoot{\sffamily\small [commalists-tools-l3]} \cfoot{\sffamily\small - \thepage{} -} \rfoot{\hyperlink{matoc}{\small\faArrowAltCircleUp[regular]}} \usepackage{hologo} \providecommand\tikzlogo{Ti\textit{k}Z} \providecommand\TeXLive{\TeX{}Live\xspace} \let\TikZ\tikzlogo \usepackage{hyperref} \urlstyle{same} \hypersetup{pdfborder=0 0 0} \usepackage[margin=2cm]{geometry} \setlength{\parindent}{0pt} \def\TPversion{0.20a} \def\TPdate{20/02/2026} \usepackage{tcolorbox} \usepackage{pgffor} \tcbuselibrary{breakable,skins,hooks,listingsutf8} %\usepackage{soul} %\sethlcolor{lightgray!25} \lstset{ language=[LaTeX]TeX,% basicstyle=\ttfamily,% keywordstyle={\color{blue}},% classoffset=0,% keywords={},% alsoletter={-},% keywordstyle={\color{blue}},% classoffset=1,% alsoletter={-},% morekeywords={commalists-tools-l3},% keywordstyle={\color{violet}},% classoffset=2,% alsoletter={-},% morekeywords={\ctshowlist,\ctsortasclist,\ctsortdeslist,\ctaddvalinlist,\ctremovevalinlist,\ctboolvalinlist,\cttestifvalinlist,\ctcountvalinlist,\ctminoflist,\ctmaxoflist,\ctmeanoflist,\ctsumoflist,\ctprodoflist,\ctreverselist,\ctgetvaluefromlist,\ctlenoflist,\ctgetindexfromlist,\ctsublist,\ctslicelist,\cttransformlist,\ctuniqlist,\ctintersectlists,\ctmergelists,\ctdifflist,\ctsymdifflist},% keywordstyle={\color{green!50!black}},% classoffset=3,% morekeywords={asc,des},% keywordstyle={\color{orange}} } \newtcblisting{DemoCode}[1]{% enhanced,width=\linewidth,% bicolor,size=title,% colback=cyan!10!white,% colbacklower=cyan!5!white,% colframe=cyan!75!black,% listing options={% breaklines=true,% breakatwhitespace=true,% style=tcblatex,basicstyle=\small\ttfamily,% tabsize=4,% commentstyle={\itshape\color{gray}}, keywordstyle={\color{blue}},% classoffset=0,% keywords={\usepackage,\includegraphics,xstring,listofitems,\readlist,\showitems,\xintFor,\xintSeq},% alsoletter={-},% keywordstyle={\color{blue}},% classoffset=1,% alsoletter={-},% morekeywords={commalists-tools-l3},% keywordstyle={\color{violet}},% classoffset=2,% alsoletter={-},% morekeywords={\ctshowlist,\ctsortasclist,\ctsortdeslist,\ctaddvalinlist,\ctremovevalinlist,\ctboolvalinlist,\cttestifvalinlist,\ctcountvalinlist,\ctminoflist,\ctmaxoflist,\ctmeanoflist,\ctsumoflist,\ctprodoflist,\ctreverselist,\ctgetvaluefromlist,\ctlenoflist,\ctgetindexfromlist,\ctsublist,\ctslicelist,\cttransformlist,\ctuniqlist,\ctintersectlists,\ctmergelists,\ctdifflist,\ctsymdifflist},% keywordstyle={\color{green!50!black}},% classoffset=3,% morekeywords={asc,des},% keywordstyle={\color{orange}} },% #1 } \newtcbinputlisting\DemoCodeFile[1]{% enhanced,width=\linewidth,% bicolor,size=title,% colback=lightgray!10!white,% colbacklower=lightgray!5!white,% colframe=lightgray!75!black,% listing options={% breaklines=true,% breakatwhitespace=true,% style=tcblatex, basicstyle=\scriptsize\ttfamily,% tabsize=2,% commentstyle={\itshape\color{gray}},% %lastline=148 },% breakable, listing only,% listing file={#1} } \NewDocumentCommand\ShowCode{ m }{% \lstinline{#1}% } \begin{document} \thispagestyle{empty} \begin{center} \begin{minipage}{0.88\linewidth} \begin{tcolorbox}[colframe=yellow,colback=yellow!15] \begin{center} \renewcommand{\arraystretch}{1.25}% \begin{tabular}{c} {\Huge \texttt{commalists-tools-l3}}\\ \\ {\large\hologo{LaTeX3}}\\ \\ {\LARGE Macros for manipulating numeral} \\ {\LARGE comma separated lists:} \\ {\LARGE sorting, adding, removing, etc} \\ \\ {\small \texttt{Version \TPversion{} -- \TPdate}} \end{tabular} \end{center} \end{tcolorbox} \end{minipage} \end{center} \begin{center} \begin{tabular}{c} \texttt{Cédric Pierquet}\\ {\ttfamily c pierquet -- at -- outlook . fr}\\ \texttt{\url{https://github.com/cpierquet/latex-packages/tree/main/commalists-tools}} \\ \end{tabular} \end{center} \hrule \vfill \begin{tcblisting}{colframe=lightgray,colback=lightgray!5,listing only} \def\mytestlist{14,10,15,11,9,10} \ctlenoflist*{\mytestlist} \ctminoflist*{\mytestlist} \ctmaxoflist*{14,10,15,11,9,10} \ctsortasclist*{\mytestlist} \ctmeanoflist*{\mytestlist} \ctremovevalinlist*{10}{\mytestlist} \cttestifvalinlist{15}{\mytestlist}{true}{false} \ctgetvaluefromlist*{\mytestlist}{3} \ctgetindexfromlist*{15}{\mytestlist} \ctsublist*{\mytestlist}{*}{4} \end{tcblisting} \begin{tcolorbox}[colframe=lightgray,colback=lightgray!5] \def\mytestlist{14,10,15,11,9,10} We consider the list: \mytestlist\par\smallskip There's \ctlenoflist*{\mytestlist} values in the list\par\smallskip The minimum value is \ctminoflist*{\mytestlist} and the maximum is \ctmaxoflist*{14,10,15,11,9,10}\par\smallskip Ascending sorted list is \ctsortasclist*{\mytestlist}\par\smallskip Mean value of the list is \ctmeanoflist*{\mytestlist}\par\smallskip If we remove the value 10, then the list is \ctremovevalinlist*{10}{\mytestlist}\par\smallskip We test if 15 is in the list: \cttestifvalinlist{15}{\mytestlist}{true}{false}\par\smallskip The third value of the list is \ctgetvaluefromlist*{\mytestlist}{3}\par\smallskip 15 is in index \ctgetindexfromlist*{15}{\mytestlist} in the list\par\smallskip Sublist [-,4] of the list is: \ctsublist*{\mytestlist}{*}{4} \end{tcolorbox} \vfill~ \hrule \vspace*{5mm} \pagebreak \phantomsection \hypertarget{matoc}{} \tableofcontents \vspace*{5mm} \pagebreak \section{Introduction} In order to load \texttt{commalists-tools-l3}, simply use: \begin{DemoCode}{listing only} \usepackage{commalists-tools-l3} \end{DemoCode} All code is written in \hologo{LaTeX3}, so no extra packages are needed. \medskip {\footnotesize\faLightbulb} See also the \href{https://ctan.org/pkg/tuple}{\texttt{tuple}} package on CTAN, which provides a more complete and fully expandable approach to numeral list operations, with an elegant \texttt{object.method} chaining syntax! \section{Global usage} \subsection{Tools} Package \texttt{commalists-tools-l3} supports (basic) manipulations on numeral comma separated lists: \begin{itemize} \item sorting; \item adding values; \item removing values; \item counting values; \item mean, sum, product; \item get value, get length; \item etc. \end{itemize} Starred versions only print the result, whereas non starred versions store the result into a macro. \medskip {\small\faLightbulb} Macros are prefixed with \ShowCode{\\ct...} (for \textsf{\textbf{\underline{c}}ommalists-\textbf{\underline{t}}ools}). \subsection{The macro for printing} \begin{DemoCode}{listing only} %just printing, with optional separator \ctshowlist[sep]{list} \end{DemoCode} \begin{DemoCode}{} \ctshowlist{1, 2,3, 4, 6} \end{DemoCode} \begin{DemoCode}{} \def\mytmplist{12, -4, 5,7 ,8, 9, 0} \ctshowlist[\,/\,]{\mytmplist} \end{DemoCode} \section{The macros for calculating} \subsection{Length, minimum, maximum} \begin{DemoCode}{listing only} %getting length of list, only printing \ctlenoflist*{list} %storing length of list into macro (\resmylen by default) \ctlenoflist{list} %getting min of list, only printing \ctminoflist*{list} %storing min of list into \macro (\resmin by default) \ctminoflist{list}[\macro] %getting max of list, only printing \ctmaxoflist*{list} %storing max of list into \macro (\resmax by default) \ctmaxoflist{list}[\macro] \end{DemoCode} \begin{DemoCode}{} %only printing \ctlenoflist*{14,10,15,11,9,10}\\ %only printing \ctminoflist*{14,10,15,11,9,10} and \ctmaxoflist*{14,10,15,11,9,10} \end{DemoCode} \begin{DemoCode}{} %storing len/min/max of list \def\mytestlist{10,14.5,20,12,8.5} \ctlenoflist{\mytestlist}[\mylen]Length of list is \mylen\ \& \ctminoflist{\mytestlist}[\mymin]Min of list is \mymin\ \& \ctmaxoflist{\mytestlist}[\mymax]Max of list is \mymax \end{DemoCode} \subsection{Mean, sum, prod} \begin{DemoCode}{listing only} %getting mean of list, only printing \ctmeanoflist*{list} %storing mean of list into \macro (\resmean by default) \ctmeanoflist{list}[\macro] %getting sum of list, only printing \ctsumoflist*{list} %storing max of list into \macro (\ressum by default) \ctsumoflist{list}[\macro] %getting prod of list, only printing \ctprodoflist*{list} %storing max of list into \macro (\resprod by default) \ctprodoflist{list}[\macro] \end{DemoCode} \begin{DemoCode}{} %only printing \ctmeanoflist*{14,10,15,11,9,10} \\ %storing \ctmeanoflist{14,10,15,11,9,10}[\mymean]\mymean \\ %only printing \ctsumoflist*{14,10,15,11,9,10} and \ctprodoflist*{14,10,15,11,9,10} \\ %storing \ctsumoflist{14,10,15,11,9,10}[\mysum]\ctprodoflist{14,10,15,11,9,10}[\myprod] The sum is \mysum\ and the prod is \myprod \end{DemoCode} \section{Macros for manipulating} \subsection{Sorting} \begin{DemoCode}{listing only} %sorting (asc), only printing \ctsortasclist*{list} %sorting (asc) and storing (overwrite) \ctsortasclist{list} %sorting (des), only printing \ctsortdeslist*{list} %sorting (des) and storing (overwrite) \ctsortdeslist{list} \end{DemoCode} \begin{DemoCode}{} %sorting (asc), only printing \ctsortasclist*{14,10,15,11.5,9,10}\\ %sorting (asc) and storing within \myreslist \def\tmpsortlist{14,10,15,11.5,9,10} \ctsortasclist{\tmpsortlist}[\myreslist]\myreslist\\ %analysing \readlist*\tmpSORTlist{\myreslist} \showitems{\tmpSORTlist} \end{DemoCode} \begin{DemoCode}{} %sorting (des), only printing \ctsortdeslist*{14,10,15,11.5,9,10}\\ %sorting (asc) and storing within \myreslist \def\tmpsortlist{14,10,15,11.5,9,10} \ctsortdeslist{\tmpsortlist}[\myreslist]\myreslist\\ %analysing \readlist*\tmpSORTlist{\myreslist} \showitems{\tmpSORTlist} \end{DemoCode} \subsection{Extract element, add/remove element} \begin{DemoCode}{listing only} %extract value, only printing \ctgetvaluefromlist*{list}{index} %extract value and storing into macro (\myelt by default) \ctgetvaluefromlist{list}{index}[\macro] \end{DemoCode} \begin{DemoCode}{} %extract value, only printing \def\listtmp{1,2,3,6,3,1,5,7,3}% \ctgetvaluefromlist*{\listtmp}{4}\par\smallskip %storing \ctgetvaluefromlist{\listtmp}{-1}[\mylastelt]The last element is \mylastelt \end{DemoCode} \begin{DemoCode}{listing only} %adding, only printing \ctaddvalinlist*{values}{list} %adding and storing (overwrite) \ctaddvalinlist{values}{list} %removing, only printing \ctremovevalinlist*{value}{list} %removing and storing (overwrite) \ctremovevalinlist{value}{list} \end{DemoCode} \begin{DemoCode}{} %only printing \ctaddvalinlist*{3}{1,2,5,6}\\ %defining and adding \def\tmpaddlist{1,2,4,5,6} \ctaddvalinlist{3}{\tmpaddlist}\tmpaddlist\\ %analysing \readlist*\tmpADDlist{\tmpaddlist} \showitems{\tmpADDlist} \end{DemoCode} \begin{DemoCode}{} %only printing \ctremovevalinlist*{3}{1,2,3,6,3,1,5,7,3}\\ %defining and removing within \mytmplist \def\tmpremlist{1,2,3,6,3,1,5,7,3} \ctremovevalinlist{3}{\tmpremlist}\mytmplist\\ %analysing \readlist*\tmpREMlist{\mytmplist} \showitems{\tmpREMlist} \end{DemoCode} \subsection{Reverse} \begin{DemoCode}{listing only} %reversing, only printing \ctreverselist*{list} %reversing and storing (overwrite) \ctreverselist{list} \end{DemoCode} \begin{DemoCode}{} %only printing \ctreverselist*{14,10,15,11,9,10}\\ %reversing and storing %storing \ctreverselist{14,10,15,11,9,10}[\myreverse]\myreverse\\ %analysing \readlist*\tmpREVERSElist{\myreverse} \showitems{\tmpREVERSElist} \end{DemoCode} \subsection{Sub-list} \begin{DemoCode}{listing only} %extracting a sub-list, only printing (* = start or end of list) \ctsublist*{list}{begin}{end} %extracting a sub-list and storing into \macro (\mysublist by default) \ctsublist{list}{begin}{end}[\macro] \end{DemoCode} \begin{DemoCode}{} \def\mylist{10,20,30,40,50,60,70} %indices 2 to 5, only printing \ctsublist*{\mylist}{2}{5}\\ %from start to index 4, only printing \ctsublist*{\mylist}{*}{4}\\ %from index 3 to end, only printing \ctsublist*{\mylist}{3}{*}\\ %whole list (* on both sides), only printing \ctsublist*{\mylist}{*}{*} \end{DemoCode} \begin{DemoCode}{} \def\mylist{10,20,30,40,50,60,70} %storing sub-list [2,5] into \myresult \ctsublist{\mylist}{2}{5}[\myresult]Sub-list [2,5]: \myresult\\ %storing sub-list [*,3] into \myresultb \ctsublist{\mylist}{*}{3}[\myresultb]Sub-list [*,3]: \myresultb\\ %storing sub-list [5,*] into \myresultc \ctsublist{\mylist}{5}{*}[\myresultc]Sub-list [5,*]: \myresultc \end{DemoCode} \begin{DemoCode}{listing only} %slicing by formula (x variable), only printing \ctslicelist*{list}{formula} %slicing by formula and storing into \macro (\myslicelist by default) \ctslicelist{list}{formula}[\macro] \end{DemoCode} \begin{DemoCode}{} \def\mylist{10,20,30,40,50,60,70,80,90,100} %even indices (2*x), only printing \ctslicelist*{\mylist}{2*x}\\ %odd indices (2*x-1), only printing \ctslicelist*{\mylist}{2*x-1}\\ %formula 3*x+1, only printing \ctslicelist*{\mylist}{3*x+1}\\ %square indices (x^2), only printing \ctslicelist*{\mylist}{x^2} \end{DemoCode} \begin{DemoCode}{} \def\mylist{10,20,30,40,50,60,70,80,90,100} %storing slice with 2*x into \myresult \ctslicelist{\mylist}{2*x}[\myresult]Slice formula 2*x: \myresult\\ %storing slice with x^2 into \myresultb \ctslicelist{\mylist}{x^2}[\myresultb]Slice formula x\^{}2: \myresultb \end{DemoCode} \subsection{Transform} \begin{DemoCode}{listing only} %transforming a list through formula, only printing \cttransformlist*[round]{list}{formula} %transforming a list through formula and storing into \macro (\mytransformlist by default) \cttransformlist*[round]{list}{formula}[\macro] \end{DemoCode} \begin{DemoCode}{} \def\mylist{10,20,30,40,50,60,70,80,90,100} %transform with 3x+1, only printing \cttransformlist*{\mylist}{3*x+1}\\ %transform with x^2, only printing \cttransformlist*{\mylist}{x^2}\\ %formula sqrt(x), only printing \cttransformlist*{10,20,30}{sqrt(x)}\\ %formula round(sqrt(x),3), only printing \cttransformlist*[3]{\mylist}{sqrt(x)}\\ \end{DemoCode} \begin{DemoCode}{} \def\mylist{10,20,30,40,50,60,70,80,90,100} %storing transform with 2*x into \myresult \cttransformlist{\mylist}{2*x}[\myresult]Transform formula 2*x:\\ \myresult\\ %storing transform with x^2-sqrt(x) into \myresultb \cttransformlist[1]{\mylist}{x^2-sqrt(x)}[\myresultb]Transform formula x\^{}2-sqrt(x):\\ \myresultb \end{DemoCode} \subsection{Remove duplicate entries} \begin{DemoCode}{listing only} %removing duplicates, only printing \ctuniqlist*{list} %removing duplicates with optional sorting [asc] or [des] \ctuniqlist*[asc]{list} \ctuniqlist*[des]{list} %removing duplicates and storing into \macro (\myuniqlist by default) \ctuniqlist{list}[\macro] \ctuniqlist[asc]{list}[\macro] \ctuniqlist[des]{list}[\macro] \end{DemoCode} \begin{DemoCode}{} \def\mylist{1,2,3,2,4,3,5,1} %without sorting, only printing \ctuniqlist*{\mylist}\\ %with ascending sort, only printing \ctuniqlist*[asc]{\mylist}\\ %with descending sort, only printing \ctuniqlist*[des]{\mylist} \end{DemoCode} \begin{DemoCode}{} \def\mylist{5,2,9,2,1,5,7,3,1} %storing without sort into \myuniq \ctuniqlist{\mylist}[\myuniq]No sort: \myuniq\\ %storing with [asc] into \myuniqasc \ctuniqlist[asc]{\mylist}[\myuniqasc]With [asc]: \myuniqasc\\ %storing with [des] into \myuniqdes \ctuniqlist[des]{\mylist}[\myuniqdes]With [des]: \myuniqdes \end{DemoCode} \section{With two lists} \subsection{Intersection} \begin{DemoCode}{listing only} %intersection of two lists, only printing \ctintersectlists*{list1}{list2} %intersection with optional sorting [asc] or [des], only printing \ctintersectlists*[asc]{list1}{list2} \ctintersectlists*[des]{list1}{list2} %intersection and storing into \macro (\myintersectlist by default) \ctintersectlists{list1}{list2}[\macro] \ctintersectlists[asc]{list1}{list2}[\macro] \ctintersectlists[des]{list1}{list2}[\macro] \end{DemoCode} \begin{DemoCode}{} \def\mylistA{1,3,5,7,9,11,13} \def\mylistB{3,6,9,12,15,7,1} %without sorting, only printing \ctintersectlists*{\mylistA}{\mylistB}\\ %with ascending sort, only printing \ctintersectlists*[asc]{\mylistA}{\mylistB}\\ %with descending sort, only printing \ctintersectlists*[des]{\mylistA}{\mylistB} \end{DemoCode} \begin{DemoCode}{} \def\mylistA{4,8,2,6,10,3,7} \def\mylistB{2,5,8,11,6,3} %storing without sort into \myinter \ctintersectlists{\mylistA}{\mylistB}[\myinter]No sort: \myinter\\ %storing with [asc] into \myinterasc \ctintersectlists[asc]{\mylistA}{\mylistB}[\myinterasc]With [asc]: \myinterasc\\ %storing with [des] into \myinterdes \ctintersectlists[des]{\mylistA}{\mylistB}[\myinterdes]With [des]: \myinterdes \end{DemoCode} \subsection{Union (merge)} \begin{DemoCode}{listing only} %union of two lists (no duplicates), only printing \ctmergelists*{list1}{list2} %union with optional sorting [asc] or [des], only printing \ctmergelists*[asc]{list1}{list2} \ctmergelists*[des]{list1}{list2} %union and storing into \macro (\mymergelist by default) \ctmergelists{list1}{list2}[\macro] \ctmergelists[asc]{list1}{list2}[\macro] \ctmergelists[des]{list1}{list2}[\macro] \end{DemoCode} \begin{DemoCode}{} \def\mylistA{1,3,5,7,9} \def\mylistB{3,6,9,12,15} %without sorting, only printing \ctmergelists*{\mylistA}{\mylistB}\\ %with ascending sort, only printing \ctmergelists*[asc]{\mylistA}{\mylistB}\\ %with descending sort, only printing \ctmergelists*[des]{\mylistA}{\mylistB} \end{DemoCode} \begin{DemoCode}{} \def\mylistA{4,8,2,6,10} \def\mylistB{2,5,8,11,6} %storing without sort into \mymerge \ctmergelists{\mylistA}{\mylistB}[\mymerge]No sort: \mymerge\\ %storing with [asc] into \mymergeasc \ctmergelists[asc]{\mylistA}{\mylistB}[\mymergeasc]With [asc]: \mymergeasc\\ %storing with [des] into \mymergedes \ctmergelists[des]{\mylistA}{\mylistB}[\mymergedes]With [des]: \mymergedes \end{DemoCode} \subsection{Difference} \begin{DemoCode}{listing only} %difference A\B (elements in A absent from B), only printing \ctdifflist*{listA}{listB} %difference with optional sorting [asc] or [des], only printing \ctdifflist*[asc]{listA}{listB} \ctdifflist*[des]{listA}{listB} %difference and storing into \macro (\mydifflist by default) \ctdifflist{listA}{listB}[\macro] \ctdifflist[asc]{listA}{listB}[\macro] \ctdifflist[des]{listA}{listB}[\macro] \end{DemoCode} \begin{DemoCode}{} \def\mylistA{1,3,5,7,9,11,13} \def\mylistB{3,7,11,15,19} %without sorting, only printing \ctdifflist*{\mylistA}{\mylistB}\\ %with ascending sort, only printing \ctdifflist*[asc]{\mylistA}{\mylistB}\\ %with descending sort, only printing \ctdifflist*[des]{\mylistA}{\mylistB} \end{DemoCode} \begin{DemoCode}{} \def\mylistA{4,8,2,6,10,3,7} \def\mylistB{2,5,8,11,6,3} %storing without sort into \mydiff \ctdifflist{\mylistA}{\mylistB}[\mydiff]No sort: \mydiff\\ %storing with [asc] into \mydiffasc \ctdifflist[asc]{\mylistA}{\mylistB}[\mydiffasc]With [asc]: \mydiffasc\\ %storing with [des] into \mydiffdes \ctdifflist[des]{\mylistA}{\mylistB}[\mydiffdes]With [des]: \mydiffdes \end{DemoCode} \subsection{Symmetric difference} \begin{DemoCode}{listing only} %symmetric difference (elements in A or B but not both), only printing \ctsymdifflist*{listA}{listB} %symmetric difference with optional sorting [asc] or [des], only printing \ctsymdifflist*[asc]{listA}{listB} \ctsymdifflist*[des]{listA}{listB} %symmetric difference and storing into \macro (\mysymdifflist by default) \ctsymdifflist{listA}{listB}[\macro] \ctsymdifflist[asc]{listA}{listB}[\macro] \ctsymdifflist[des]{listA}{listB}[\macro] \end{DemoCode} \begin{DemoCode}{} \def\mylistA{1,3,5,7,9,11,13} \def\mylistB{3,7,11,15,19} %without sorting, only printing \ctsymdifflist*{\mylistA}{\mylistB}\\ %with ascending sort, only printing \ctsymdifflist*[asc]{\mylistA}{\mylistB}\\ %with descending sort, only printing \ctsymdifflist*[des]{\mylistA}{\mylistB} \end{DemoCode} \begin{DemoCode}{} \def\mylistA{4,8,2,6,10,3,7} \def\mylistB{2,5,8,11,6,3} %storing without sort into \mysymdiff \ctsymdifflist{\mylistA}{\mylistB}[\mysymdiff]No sort: \mysymdiff\\ %storing with [asc] into \mysymdiffasc \ctsymdifflist[asc]{\mylistA}{\mylistB}[\mysymdiffasc]With [asc]: \mysymdiffasc\\ %storing with [des] into \mysymdiffdes \ctsymdifflist[des]{\mylistA}{\mylistB}[\mysymdiffdes]With [des]: \mysymdiffdes \end{DemoCode} \section{Macros with testing} \subsection{Value in list ?} \begin{DemoCode}{listing only} %testing if value is in list, with boolean result in \macro (\resisinlist by default) \ctboolvalinlist{value}{list}[\macro] %conditionnal test if value is in list, according to xint syntax \cttestifvalinlist{3}{0,1,2,3}{true}{false} \end{DemoCode} \begin{DemoCode}{} %test with xint syntax \cttestifvalinlist{-1}{0,1,2,3}{true}{false}\\ %test with xint syntax \cttestifvalinlist{3}{0,1,2,3}{true}{false}\\ %boolean macro \def\myteslist{0,5,10,5,6,9,7,8} \ctboolvalinlist{5}{\myteslist}[\resisinlist]\resisinlist \end{DemoCode} \subsection{Count value} \begin{DemoCode}{listing only} %counting value, only printing \ctcountvalinlist*{value}{list} %counting value, with result in \macro (\rescount by default) \ctcountvalinlist{value}{list}[\macro] \end{DemoCode} \begin{DemoCode}{} %only printing \ctcountvalinlist*{8}{1,2,3,4,5,6,6,7,8,8,8,9}\\ %storing \def\tmpcountlist{1,2,3,4,5,6,6,7,8,8,8,9} \ctcountvalinlist{6}{\tmpcountlist}[\rescountsix]\rescountsix\\ \ctcountvalinlist{10}{\tmpcountlist}[\rescountten]\rescountten \end{DemoCode} \subsection{Get index} \begin{DemoCode}{listing only} %index value (first occurency), only printing \ctgetindexfromlist*{value}{list} %index value (first occurency), with result in \macro (\resmyindex by default) \ctgetindexfromlist{value}{list}[\macro] \end{DemoCode} \begin{DemoCode}{} %only printing \ctgetindexfromlist*{8}{1,2,3,4,5,6,6,7,8,8,8,9}\\ %storing \def\tmpindexlist{1,2,3,4,5,6,6,7,8,8,8,9} \ctgetindexfromlist{6}{\tmpindexlist}[\resindexsix]\resindexsix\\ \ctgetindexfromlist{10}{\tmpindexlist}[\resindexten]\resindexten \end{DemoCode} \pagebreak \section{History} \texttt{0.20a: Sub-list extraction + transform list + merge/intersection + improvements} \texttt{0.1.9: Improvements with \hologo{LaTeX3}, tks to \textit{ankaa3908}} \texttt{0.1.8: Get index from value} \texttt{0.1.7: Improvements with \hologo{LaTeX3}} \texttt{0.1.6: Initial version,code written in \hologo{LaTeX3}} \section{The code} \DemoCodeFile{commalists-tools-l3.sty} \end{document}