Extrahieren einer Liste unterschiedlicher Werte aus einer anderen Liste (Entfernen von Duplikaten)

Extrahieren einer Liste unterschiedlicher Werte aus einer anderen Liste (Entfernen von Duplikaten)

Angenommen, ich habe eine Liste definiert über \def\zList{0,0,1,1,1,2,2,10}.

Wie kann ich eine (durch Kommas getrennte) Liste erhalten 0,1,2,10, die die eindeutigen/unterschiedlichen Werte in enthält 0,0,1,1,1,2,2,10?

Gibt es vielleicht eine Möglichkeit mit pgfmath?(Ich brauche das Ganze auch in komplexeren Kontexten [pgfplots/-table], pgfmathwäre also nicht so schlimm ...)

Bildbeschreibung hier eingeben

\documentclass[a4paper]{article}
\usepackage{tikz}
\begin{document}
\def\zList{0,0,1,1,1,2,2,10}

\let\List=\empty% create List
\foreach \n  in \zList {%
\pgfmathparse{\n}%  <--- A clever method needed here
  \ifx\empty\List{} \xdef\List{\pgfmathresult}%
  \else \xdef\List{\List,\pgfmathresult}%
  \fi}
  
Show Zero List: \zList

Show List-Actual: \List

Show List-Target: 0,1,2,10
\end{document}

Antwort1

Sie können Duplikate entfernen mitexpl3

\ExplSyntaxOn
\cs_new_eq:NN \removeclistdupes \clist_remove_duplicates:N
\ExplSyntaxOff
\Removeclistdupes\List

Ein vollständiges Beispiel

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

Antwort2

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

Bildbeschreibung hier eingeben

Wenn Sie mit Token-Listen nicht vertraut sind, gibt es hier eine Version, die \defstattdessen s verwendet.

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

Antwort3

Edit: Jemand hat darum gebeten, "unnötige" Nullen zu entfernen. Das geht mit \FPclipdem fp-Paket.

Wenn Sie das Aussortieren mit den von bereitgestellten Tools durchführen möchten tikz, können Sie eine verschachtelte Iteration der bereits erstellten Liste in Betracht ziehen:

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

Bildbeschreibung hier eingeben

Erläuterung:

Du hast die⟨vom Benutzer übergebene Liste⟩( \zList) und das⟨Bisher erstellte sortierte Liste⟩( \List).

Mit jedem Element \nder⟨vom Benutzer übergebene Liste⟩Mach Folgendes:

  • Setzen Sie ein Flag ( \ifalreadyinserted/ \alreadyinsertedfalse/ \alreadyinsertedtrue), um anzuzeigen, dass es möglicherweise notwendig ist, dieses Element \nin das⟨Bisher erstellte sortierte Liste⟩.

  • "Schauen Sie sich jedes Element \oder⟨Bisher erstellte sortierte Liste⟩um herauszufinden, ob das Element \nder⟨vom Benutzer übergebene Liste⟩muss in das⟨Bisher erstellte sortierte Liste⟩:

    Solange der Wert des Elements \oder⟨Bisher erstellte sortierte Liste⟩ist nicht größer als der Wert des Elements \nder⟨vom Benutzer übergebene Liste⟩, das Element \nder⟨vom Benutzer übergebene Liste⟩muss nicht in den⟨Bisher erstellte sortierte Liste⟩.

    Wenn die Flagge immer noch anzeigt, dass das Element möglicherweise \nin das⟨Bisher erstellte sortierte Liste⟩tritt es zum ersten Mal aufdass der Wert des Elements \oder⟨Bisher erstellte sortierte Liste⟩ist größer als der Wert des Elements \nder⟨vom Benutzer übergebene Liste⟩, das Element \nder⟨vom Benutzer übergebene Liste⟩muss in das⟨Bisher erstellte sortierte Liste⟩vor dem Element \oder⟨Bisher erstellte sortierte Liste⟩.
    Wenn es das erste Mal auftritt... – das Flag wird benötigt, um herauszufinden, ob es das erste Mal ist.

    Wenn der Wert des Elements \oder⟨Bisher erstellte sortierte Liste⟩ist größer oder gleich dem Wert des Elements \nder⟨vom Benutzer übergebene Liste⟩, dann muss das Flag gesetzt werden, um anzuzeigen, dass es nicht notwendig ist, das Element \ndes⟨vom Benutzer übergebene Liste⟩in die⟨vom Benutzer übergebene Liste⟩.

  • Wenn nach Betrachtung aller Elemente \oder⟨Bisher erstellte sortierte Liste⟩Die Flagge zeigt immer noch an, dass möglicherweise das Element \ndes⟨vom Benutzer übergebene Liste⟩in die⟨Bisher erstellte sortierte Liste⟩, dann zeigt dies an, dass der Wert des Elements \nder⟨vom Benutzer übergebene Liste⟩ist größer als die Werte aller Elemente \o, die sich bereits im⟨Bisher erstellte sortierte Liste⟩und dass daher das Element \nder⟨vom Benutzer übergebene Liste⟩muss angehängt werden an die⟨Bisher erstellte sortierte Liste⟩.

Antwort4

Der Abwechslung halber hier eine LuaLaTeX-basierte Lösung.

Die Eingabezeichenfolge – definiert beispielsweise durch \zList– kann Zahlen, Makros (außer \zListsich selbst), die zu Zahlen erweitert werden, und Zeichenfolgen enthalten, die eine Liste durch Kommas getrennter Zahlen enthalten. Die Zahlen müssen nicht in aufsteigender Reihenfolge sortiert sein.

\uniqueextrahiert die eindeutigen sortierten Zahlen, die in enthalten sind \zList.

Bildbeschreibung hier eingeben

% !TeX program = lualatex
\documentclass{article}

%% Lua-side code
\usepackage{luacode} % for 'luacode' environment
\begin{luacode}
function string_to_table (str)
   local fields = {} -- initialize the table
   str:gsub( "([^,]*)" , function ( c ) 
                 -- strip off anyleading and trailing whitespace:
                 c = c:gsub ( "^%s*(.-)%s*$" , "%1" )
                 -- insert 'c' in 'fields'
                 table.insert ( fields , tonumber(c) )   
               end )
   return fields
end
function remove_duplicate_entries ( t ) 
   -- from https://stackoverflow.com/a/20067270/1014365
   local hash = {}
   local res = {}
   for _,v in ipairs(t) do
      if (not hash[v]) then
         res[#res+1] = v 
         hash[v] = true
      end
   end
   return res
end
function unique ( s )
   local t
   -- Convert string 's' to a Lua table:
   t = string_to_table ( s )
   -- Sort the table entries in ascending order:
   table.sort ( t , function(a,b) return a<b end)
   -- Retain the unique elements:
   t = remove_duplicate_entries ( t )
   -- Convert table back to string and print:
   tex.sprint ( table.concat ( t, "," )  )
end
\end{luacode}
%% LaTeX-side code:
\newcommand\unique[1]{\directlua{unique(\luastring{#1})}}

\begin{document}
\def\mynum{10}
\newcommand\mystr{"\mynum,0"}
\def\zList{0,10,1,1,2,2,1,0,\mynum,\mystr}

\zList

\unique{\zList}
\end{document}

verwandte Informationen