다른 목록에서 고유 값 목록 추출(중복 제거)

다른 목록에서 고유 값 목록 추출(중복 제거)

를 통해 정의된 목록이 있다고 가정합니다 \def\zList{0,0,1,1,1,2,2,10}.

0,1,2,10의 고유한/고유한 값이 포함된 (쉼표로 구분된) 목록을 어떻게 얻을 수 있습니까 0,0,1,1,1,2,2,10?

아마도 방법이 있을까요 pgfmath?(또한 더 복잡한 컨텍스트 [pgfplots/-table]에서도 모든 것이 필요하므로 그렇게 pgfmath나쁘지는 않을 것입니다 ...)

여기에 이미지 설명을 입력하세요

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

답변1

다음을 사용하여 중복 항목을 제거할 수 있습니다.expl3

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

전체 예

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

답변2

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

여기에 이미지 설명을 입력하세요

토큰 목록이 불편하다면 \def대신 s를 사용하는 버전이 있습니다.

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

답변3

편집: 누군가 "불필요한" 0을 잘라달라고 요청했습니다. \FPclipfp-package에서 이 작업을 수행할 수 있습니다 .

에서 제공하는 도구를 사용하여 정렬을 수행하려는 경우 tikz이미 구성된 목록에 중첩된 반복을 고려할 수 있습니다.

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

여기에 이미지 설명을 입력하세요

설명:

당신은⟨사용자가 전달한 목록⟩( \zList) 그리고⟨지금까지 생성된 정렬 목록⟩( \List).

각 요소 \n별로⟨사용자가 전달한 목록⟩다음을 수행하십시오.

  • 해당 \ifalreadyinserted요소 를​​\alreadyinsertedfalse\alreadyinsertedtrue\n⟨지금까지 생성된 정렬 목록⟩.

  • \o각 요소를 "보세요".⟨지금까지 생성된 정렬 목록⟩요소가 있는지 확인하기 위해\n⟨사용자가 전달한 목록⟩에 삽입해야 합니다.⟨지금까지 생성된 정렬 목록⟩:

    \o요소의 가치가 있는 한⟨지금까지 생성된 정렬 목록⟩\n해당 요소의 값보다 크지 않습니다.⟨사용자가 전달한 목록⟩\n, 의 요소⟨사용자가 전달한 목록⟩에 삽입할 필요는 없습니다.⟨지금까지 생성된 정렬 목록⟩.

    \n플래그가 여전히 요소를 삽입 해야 할 수도 있음을 나타내는 경우⟨지금까지 생성된 정렬 목록⟩, 처음으로 발생합니다.\o그 요소 의 가치는⟨지금까지 생성된 정렬 목록⟩\n해당 요소의 값보다 큽니다.⟨사용자가 전달한 목록⟩\n, 의 요소⟨사용자가 전달한 목록⟩에 삽입해야 합니다.⟨지금까지 생성된 정렬 목록⟩요소 \o앞에⟨지금까지 생성된 정렬 목록⟩.
    처음 발생하는 경우... - 처음 발생하는지 확인하려면 플래그가 필요합니다.

    \o해당 요소의 값이⟨지금까지 생성된 정렬 목록⟩\n해당 요소의 값보다 크거나 같습니다.⟨사용자가 전달한 목록⟩\n의 요소를 삽입할 필요가 없음을 나타내기 위해 플래그를 설정해야 합니다.⟨사용자가 전달한 목록⟩⟨사용자가 전달한 목록⟩.

  • \o모든 요소 를 ​​살펴본 후⟨지금까지 생성된 정렬 목록⟩\n플래그는 여전히 해당 요소를 삽입해야 할 수도 있음을 나타냅니다.⟨사용자가 전달한 목록⟩⟨지금까지 생성된 정렬 목록⟩, 이는 해당 요소 \n의 값을 나타냅니다.⟨사용자가 전달한 목록⟩\o이미 있는 모든 요소의 값보다 큽니다.⟨지금까지 생성된 정렬 목록⟩그러므로 그 요소 \n⟨사용자가 전달한 목록⟩에 추가해야 합니다.⟨지금까지 생성된 정렬 목록⟩.

답변4

다양성을 위해 LuaLaTeX 기반 솔루션이 있습니다.

예를 들어 다음으로 정의된 입력 문자열에는 숫자, 숫자로 확장되는 매크로(자체 제외), 쉼표로 구분된 숫자 목록이 포함된 문자열이 \zList포함될 수 있습니다 . \zList숫자를 오름차순으로 정렬할 필요는 없습니다.

\unique에 포함된 고유한 정렬 숫자를 추출합니다 \zList.

여기에 이미지 설명을 입력하세요

% !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}

관련 정보