Extract a list of distinct values from another list (remove dupes)
You could remove duplicates using expl3
\ExplSyntaxOn
\cs_new_eq:NN \removeclistdupes \clist_remove_duplicates:N
\ExplSyntaxOff
\Removeclistdupes\List
A full example
\documentclass[a4paper]{article}
\usepackage{expl3}
\ExplSyntaxOn
\cs_new_eq:NN \removeclistdupes \clist_remove_duplicates:N
\ExplSyntaxOff
\usepackage{tikz}
\begin{document}
\def\zList{0,0,1,1,1,2,2,10}
\let\List=\empty% create List
zList
\foreach \n in \zList {%
\pgfmathparse{\n}% <--- A clever method needed here
\ifx\empty\List{} \xdef\List{\pgfmathresult}%
\else \xdef\List{\List,\pgfmathresult}%
\fi}
\removeclistdupes\List
Show Zero List: \zList
Show List-Actual: \List
Show List-Target: 0,1,2,10
\end{document}
Edit: Someone asked to have "unnecessary" zeros clipped. You can do this with \FPclip
from the fp-package.
If you wish to do the sorting-out with the tools provided by tikz
, you can consider nested iteration on the already constructed list:
\documentclass[a4paper]{article}
\usepackage[nomessages]{fp}
\usepackage{tikz}
\usetikzlibrary{math}
% pgfmanual.pdf promises a ot of things to work which often don't due to bugs.
% E.g., with tikz/pgf 3.1.1 by default there is no \ifpgfmathfloatparseactive
% and evaluation of if-expressions via \pgfmathfloattofixed seems corrupted.
% \newif\ifpgfmathfloatparseactive
% \pgfmathfloatparseactivefalse
%
% Afaik current release (the date of writing this answer is
% August 28, 2020) is 3.1.5b.
% Seems things are fixed there.
\newcommand\PassFirstToSecond[2]{#2{#1}}%
\newif\ifalreadyinserted
\begin{document}
\newcommand\one{1}
\newcommand\two{2}
\newcommand\onecommaeight{1.8}
\newcommand*\zList{0,0,1,1,1.8,1.6754376,\one,\two,1,2,4+4,2,10,1.7,1.7,\onecommaeight,8,1.0}
\newcommand*\List{}% create List
\foreach \n in \zList {%
\pgfmathparse{\n}%
\let\n=\pgfmathresult
\FPclip{\n}{\n}%
\expandafter\PassFirstToSecond\expandafter{\List}{%
\def\List{}%
\global\alreadyinsertedfalse
\foreach \o in
}{%
\tikzmath{%
if (\o <= \n) then {{\xdef\List{\List\ifx\List\empty\else,\fi\o}};}%
else {{\xdef\List{\List\ifx\List\empty\else,\fi\ifalreadyinserted\else\n,\fi\o}};};%
if (\o >= \n) then {{\global\alreadyinsertedtrue};};%
}%
}%
\ifalreadyinserted\else
\xdef\List{\List\ifx\List\empty\else,\fi\n}%
\fi
}
Show Zero List: \texttt{\frenchspacing\string\zList: \meaning\zList}
Show List-Actual: \texttt{\frenchspacing\string\List: \meaning\List}
\end{document}
Explanation:
You have the ⟨list passed by the user⟩ (\zList
) and the ⟨sorted list created so far⟩ (\List
).
With each element \n
of the ⟨list passed by the user⟩ do the following:
Set a flag (
\ifalreadyinserted
/\alreadyinsertedfalse
/\alreadyinsertedtrue
) to indicate that there might be need to insert that element\n
into the ⟨sorted list created so far⟩."Look" at each element
\o
of the ⟨sorted list created so far⟩ for finding out if the element\n
of the ⟨list passed by the user⟩ needs to be inserted into the ⟨sorted list created so far⟩ :As long as the value of the element
\o
of the ⟨sorted list created so far⟩ is not greater than the value of the element\n
of the ⟨list passed by the user⟩, the element\n
of the ⟨list passed by the user⟩ does not need to be inserted into the ⟨sorted list created so far⟩.If, while the flag still indicates that there might be need to insert the element
\n
into the ⟨sorted list created so far⟩, it occurs the first time that the value of the element\o
of the ⟨sorted list created so far⟩ is greater than the value of the element\n
of the ⟨list passed by the user⟩, the element\n
of the ⟨list passed by the user⟩ needs to be inserted into the ⟨sorted list created so far⟩ before the element\o
of the ⟨sorted list created so far⟩.
If it occurs the first time...—the flag is needed for finding out if it is the first time.If the value of the element
\o
of the ⟨sorted list created so far⟩ is greater than or equal to the value of the element\n
of the ⟨list passed by the user⟩, then the flag needs to be set to indicate that there is no need to insert the element\n
of the ⟨list passed by the user⟩ into the ⟨list passed by the user⟩.If after looking at all elements
\o
of the ⟨sorted list created so far⟩ the flag still indicates that there might be need to insert the element\n
of the ⟨list passed by the user⟩ into the ⟨sorted list created so far⟩, then this indicates that the value of the element\n
of the ⟨list passed by the user⟩ is greater than the values of all elements\o
that are already in the ⟨sorted list created so far⟩ and that therefore the element\n
of the ⟨list passed by the user⟩ needs to be appended to the ⟨sorted list created so far⟩.
\documentclass{article}
\usepackage{listofitems,pgffor}
\newcounter{zcount}
\newtoks\mytoks
\mytoks{}
\expandafter\def\csname zmatch0\endcsname{-9999999}% NUMBER NOT IN LIST
\begin{document}
\def\zList{0,0,1,1,1,2,2,10}
The original list is \zList
\readlist\zdata{\zList}
\foreachitem\z\in\zdata[]{%
\gdef\ztest{F}%
\foreach\zcnt in {0,...,\thezcount}{%
\ifnum\z=\csname zmatch\zcnt\endcsname\relax\gdef\ztest{T}\fi%
}%
\if F\ztest
\stepcounter{zcount}%
\expandafter\gdef\csname zmatch\thezcount\expandafter\endcsname
\expandafter{\z}%
\expandafter\ifx\expandafter\relax\the\mytoks\relax
\else\mytoks\expandafter{\the\mytoks,}\fi
\mytoks\expandafter{\the\expandafter\mytoks\z}%
\fi
}
The new list is \the\mytoks
\end{document}
If you are not comfortable with token lists, then here is a version that uses \def
s, instead
\documentclass{article}
\usepackage{listofitems,pgffor}
\newcounter{zcount}
\expandafter\def\csname zmatch0\endcsname{-9999999}% NUMBER NOT IN LIST
\begin{document}
\def\zList{0,0,1,1,1,2,2,10}
The original list is \zList
\readlist\zdata{\zList}
\foreachitem\z\in\zdata[]{%
\gdef\ztest{F}%
\foreach\zcnt in {0,...,\thezcount}{%
\ifnum\z=\csname zmatch\zcnt\endcsname\relax\gdef\ztest{T}\fi%
}%
\if F\ztest
\stepcounter{zcount}%
\expandafter\xdef\csname zmatch\thezcount\expandafter\endcsname
\expandafter{\z}%
\ifnum\thezcount=1\relax
\xdef\zNewList{\csname zmatch1\endcsname}%
\else
\xdef\zNewList{\zNewList,\csname zmatch\thezcount\endcsname}
\fi
\fi
}
The new list is \zNewList
\end{document}