% !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.20b}
\def\TPdate{24/03/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,\ctgetvaluefromcycllist},%
		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}
%extract value (cyclic list), only printing
\ctgetvaluefromcycllist*{list}{index}
%extract value (cyclic list) and storing into macro (\myelt by default)
\ctgetvaluefromcycllist{list}{index}[\macro]
\end{DemoCode}

\begin{DemoCode}{}
%extract value (cyclic list), only printing
\def\listtmp{A,B,C,D,E,F}%
\ctgetvaluefromcycllist*{\listtmp}{10}\par\smallskip
%storing
\ctgetvaluefromcycllist{\listtmp}{-10}[\myelt]\myelt
\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.20b: Extract element with cyclic version of list}

\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}
