を介して定義されたリストがあるとします\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
\FPclip
編集: 誰かが「不要な」ゼロをクリップするように要求しました。これはfp パッケージから実行できます。
が提供するツールを使用してソートを行う場合は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}