TeX - LaTeX Asked on January 27, 2021
Suppose I have a list defined via defzList{0,0,1,1,1,2,2,10}
.
How can I obtain a (comma-separated) list 0,1,2,10
that contains the unique/distinct values in 0,0,1,1,1,2,2,10
?
Is there perhaps a way with pgfmath
? (I also need the whole thing in more complex contexts [pgfplots/-table], so pgfmath
wouldn’t be so bad …)
documentclass[a4paper]{article}
usepackage{tikz}
begin{document}
defzList{0,0,1,1,1,2,2,10}
letList=empty% create List
foreach n in zList {%
pgfmathparse{n}% <--- A clever method needed here
ifxemptyList{} xdefList{pgfmathresult}%
else xdefList{List,pgfmathresult}%
fi}
Show Zero List: zList
Show List-Actual: List
Show List-Target: 0,1,2,10
end{document}
You could remove duplicates using expl3
ExplSyntaxOn
cs_new_eq:NN removeclistdupes clist_remove_duplicates:N
ExplSyntaxOff
RemoveclistdupesList
A full example
documentclass[a4paper]{article}
usepackage{expl3}
ExplSyntaxOn
cs_new_eq:NN removeclistdupes clist_remove_duplicates:N
ExplSyntaxOff
usepackage{tikz}
begin{document}
defzList{0,0,1,1,1,2,2,10}
letList=empty% create List
zList
foreach n in zList {%
pgfmathparse{n}% <--- A clever method needed here
ifxemptyList{} xdefList{pgfmathresult}%
else xdefList{List,pgfmathresult}%
fi}
removeclistdupesList
Show Zero List: zList
Show List-Actual: List
Show List-Target: 0,1,2,10
end{document}
Correct answer by Joseph Wright on January 27, 2021
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.
% newififpgfmathfloatparseactive
% pgfmathfloatparseactivefalse
%
% Afaik current release (the date of writing this answer is
% August 28, 2020) is 3.1.5b.
% Seems things are fixed there.
newcommandPassFirstToSecond[2]{#2{#1}}%
newififalreadyinserted
begin{document}
newcommandone{1}
newcommandtwo{2}
newcommandonecommaeight{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}%
letn=pgfmathresult
FPclip{n}{n}%
expandafterPassFirstToSecondexpandafter{List}{%
defList{}%
globalalreadyinsertedfalse
foreach o in
}{%
tikzmath{%
if (o <= n) then {{xdefList{ListifxListemptyelse,fio}};}%
else {{xdefList{ListifxListemptyelse,fiifalreadyinsertedelsen,fio}};};%
if (o >= n) then {{globalalreadyinsertedtrue};};%
}%
}%
ifalreadyinsertedelse
xdefList{ListifxListemptyelse,fin}%
fi
}
Show Zero List: texttt{frenchspacingstringzList: meaningzList}
Show List-Actual: texttt{frenchspacingstringList: meaningList}
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⟩.
Answered by Ulrich Diez on January 27, 2021
documentclass{article}
usepackage{listofitems,pgffor}
newcounter{zcount}
newtoksmytoks
mytoks{}
expandafterdefcsname zmatch0endcsname{-9999999}% NUMBER NOT IN LIST
begin{document}
defzList{0,0,1,1,1,2,2,10}
The original list is zList
readlistzdata{zList}
foreachitemzinzdata[]{%
gdefztest{F}%
foreachzcnt in {0,...,thezcount}{%
ifnumz=csname zmatchzcntendcsnamerelaxgdefztest{T}fi%
}%
if Fztest
stepcounter{zcount}%
expandaftergdefcsname zmatchthezcountexpandafterendcsname
expandafter{z}%
expandafterifxexpandafterrelaxthemytoksrelax
elsemytoksexpandafter{themytoks,}fi
mytoksexpandafter{theexpandaftermytoksz}%
fi
}
The new list is themytoks
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}
expandafterdefcsname zmatch0endcsname{-9999999}% NUMBER NOT IN LIST
begin{document}
defzList{0,0,1,1,1,2,2,10}
The original list is zList
readlistzdata{zList}
foreachitemzinzdata[]{%
gdefztest{F}%
foreachzcnt in {0,...,thezcount}{%
ifnumz=csname zmatchzcntendcsnamerelaxgdefztest{T}fi%
}%
if Fztest
stepcounter{zcount}%
expandafterxdefcsname zmatchthezcountexpandafterendcsname
expandafter{z}%
ifnumthezcount=1relax
xdefzNewList{csname zmatch1endcsname}%
else
xdefzNewList{zNewList,csname zmatchthezcountendcsname}
fi
fi
}
The new list is zNewList
end{document}
Answered by Steven B. Segletes on January 27, 2021
For the sake of variety, here's a LuaLaTeX-based solution.
The input string -- defined by, say, zList
-- may contain numbers, macros (except zList
itself) that expand to numbers, and strings that contain a list of comma-separated numbers. The numbers needn't be sorted in ascending order.
unique
extracts the unique sorted numbers contained in 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:
newcommandunique[1]{directlua{unique(luastring{#1})}}
begin{document}
defmynum{10}
newcommandmystr{"mynum,0"}
defzList{0,10,1,1,2,2,1,0,mynum,mystr}
zList
unique{zList}
end{document}
Answered by Mico on January 27, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP