samcarter
For a recent answer, I generate random integers and wanted to count how often each of the integers occurred and store this information for later use. To do this I used some dirty hack and generated n counters, but there is most certainly a much better way to do this.

Maximal Hacky Example:


\documentclass{article}
\usepackage{tikz}
\pgfmathsetseed{\number\pdfrandomseed}

\def\numcolors{10}

% Generating n counters
\newcounter{bar}
\foreach \x in {1,...,\numcolors}{
\setcounter{bar}{\x}
\newcounter{mycount\alph{bar}}
}

\begin{document}

% generating 10000 random integers between 1 and n
\foreach \x in {1,...,10000}{%
\pgfmathrandominteger{\myran}{1}{\numcolors}%
\setcounter{bar}{\myran}%
}%

% how often was each integer chosen?
\foreach \x in {1,...,\numcolors}{%
\setcounter{bar}{\x}%
\x : \csname themycount\alph{bar}\endcsname \par
}

\end{document}


frougon
I did something like that [in this TeX.SE answer](https://tex.stackexchange.com/a/522374). Here is a simple adaptation to your case, which uses non-expandable “setup code.” \computeAndDisplayDistribution prints a table with the frequency of each value obtained from expl3 *<integer expression>* #3 evaluated #1 times. “Setup code” #2 may contain non-expandable material and is executed upon each iteration, right before computing #3.

If you want the number of occurrences of each value instead of their frequencies, you can simply remove the / (#1) division in the following line:


{ \use_i:nn ##1 & \fp_eval:n { \use_ii:nn ##1 / (#1) } \\ }


In this case, the \fpeval:n command wouldn't be needed anymore and the line could be reduced to:


{ \use_i:nn ##1 & \use_ii:nn ##1 \\ }


Here is the full code:


\documentclass{article}
\usepackage{pgfmath}       % only for the user code (\pgfmathrandominteger)
\usepackage{xparse}
\usepackage{booktabs}
\usepackage{siunitx}
\sisetup{round-mode = places, round-precision=4}

\ExplSyntaxOn

% Code to compute the distribution of values
\prop_new:N \l_my_prop          % nb of occurrences for each obtained result
\int_new:N \l_my_value_int
\int_new:N \l_my_count_int
\seq_new:N \l_my_values_seq
\tl_new:N \l_my_tabular_data_tl

\cs_new_protected:Npn \my_compute_distribution:nnn #1#2#3
{
\prop_clear:N \l_my_prop
\int_step_inline:nn {#1}
{
#2                      % Execute the “setup code”
\int_set:Nn \l_my_value_int {#3}

\prop_if_in:NVTF \l_my_prop \l_my_value_int
{
\prop_get:NVN \l_my_prop \l_my_value_int \l_tmpa_tl
\int_set:Nn \l_my_count_int { 1 + \l_tmpa_tl }
\prop_put:NVV \l_my_prop \l_my_value_int \l_my_count_int
}
{ \prop_put:NVn \l_my_prop \l_my_value_int { 1 } }
}
}

\NewDocumentCommand \computeAndDisplayDistribution { m m m }
{
\my_compute_distribution:nnn {#1} {#2} {#3}
\seq_clear:N \l_my_values_seq

\prop_map_inline:Nn \l_my_prop
{ \seq_put_right:Nn \l_my_values_seq { {##1} {##2} } }

\seq_sort:Nn \l_my_values_seq
{
\int_compare:nNnTF { \use_i:nn ##1 } > { \use_i:nn ##2 }
{ \sort_return_swapped: }
{ \sort_return_same: }
}

\tl_clear:N \l_my_tabular_tl
\seq_map_inline:Nn \l_my_values_seq
{
\tl_put_right:Nn \l_my_tabular_data_tl
{ \use_i:nn ##1 & \fp_eval:n { \use_ii:nn ##1 / (#1) } \\ }
}

\begin{tabular}{rS}
\toprule
{ Value } & { Frequency } \\ \midrule
\tl_use:N \l_my_tabular_data_tl
\bottomrule
\end{tabular}
}

\ExplSyntaxOff

\pgfmathsetseed{\number\pdfrandomseed}
\newcommand*{\numberOfSamples}{10000}
\newcommand*{\minValue}{1}
\newcommand*{\maxValue}{10}

\begin{document}

% Generate \numberOfSamples random integers between \minValue and \maxValue
\computeAndDisplayDistribution
{\numberOfSamples}
{\pgfmathrandominteger{\myran}{\minValue}{\maxValue}}
{\myran}

\end{document}

![frequencies.png](/image?hash=586baabcd2ae0b9e147a680a58dd018ed42f4c6d410ba7d306b75f0e7100102e)
Skillmon
The following was mainly written just for the sake of writing it. It has several limitations:

- only integers >= 0 and <= the number of available count-registers in the used engine can be counted.
- the count registers must not be used for other things while the code counts them (this means no Ti*k*Z functions, etc.)
- the entire list of integers has to already exist as one comma separated list (empty list elements are ignored)


\documentclass[]{article}

\makeatletter
\long\def\@secondofthree#1#2#3{#2}
\newcommand\countints[1]
{%
\begingroup
\def\countints@elements{,}%
\let\countints@final\@empty
\def\countints@max{0}%
\def\countints@min{2147483647}%
\countints@count#1,\end,%
\expandafter\countints@finalize\expandafter{\countints@min}%
\expandafter
\endgroup
\countints@final
}
\newcommand*\countints@ifknown[1]
{%
\def\countints@ifknown@##1,#1,##2\end
{\countints@ifempty{##2}}%
\expandafter\countints@ifknown@\countints@elements#1,\end
\@secondoftwo\@firstoftwo
}
\newcommand\countints@ifempty[1]
{%
\if\relax\detokenize{#1}\relax
\expandafter\@secondofthree
\fi
\@secondoftwo
}
\def\countints@count#1,%
{%
\countints@ifempty{#1}%
\countints@count
{%
\ifx\end#1%
\expandafter\@gobbletwo
\fi
\@firstofone
{%
\countints@ifknown{#1}%
{%
\edef\countints@elements
{\unexpanded\expandafter{\countints@elements#1,}}%
\ifnum#1>\countints@max
\def\countints@max{#1}%
\fi
\ifnum#1<\countints@min
\def\countints@min{#1}%
\fi
\count#1\@ne
}%
\countints@count
}%
}%
}
\newcommand*\countints@finalize[1]
{%
\unless\ifnum#1>\countints@max
\countints@ifknown{#1}%
{%
\edef\countints@final
{%
\unexpanded\expandafter{\countints@final\countints@output{#1}}%
{\the\count#1}%
}%
}%
{}%
\expandafter\@secondoftwo
\fi
\@gobble
{\expandafter\countints@finalize\expandafter{\the\numexpr#1+1}}%
}

% has to be adapted for the use case. It gets two arguments, the first is the
% value the second the number of times that value was found in the list
\newcommand*\countints@output[2]
{%
#1 & \strip@pt\dimexpr#2pt/\mylistlength\relax \\
}
\makeatother

% generating the list
\usepackage{tikz}
\newcommand*\mylist{}
\newcommand*\mylistlength{1000}
\newcommand*\numcolors{10}
\pgfmathsetseed{\number\pdfrandomseed}
\foreach\x in{1,...,\mylistlength}
{%
\pgfmathrandominteger{\myran}{1}{\numcolors}%
\xdef\mylist{\mylist\myran,}%
}

\usepackage{booktabs}

\begin{document}
\begin{tabular}{rr}
\toprule
Value & Frequency \\
\midrule
\expandafter\countints\expandafter{\mylist}
\bottomrule
\end{tabular}
\end{document}


![count_n_thingies.png](/image?hash=d09cb1ea5d7b54ae329caa96d243c1e7ca3522aa70d002315cbc45ecf0d68721)
marmot
These are just some random thoughts. However, I think that one may not necessarily want to define a new scheme for something that exists and gets widely used. pgf keys already allow us to define families of keys that we can manipulate. To see what I mean, consider the (somewhat silly, I know) code

\documentclass{article}
\usepackage{pgf}
\begin{document}
\pgfkeys{/samcarter/.cd,2/.initial=1}%
My array entry with the id 2 has the value \pgfkeysvalueof{/samcarter/2}.

\bigskip
Now we can manipulate the array at will''.
\pgfkeys{/samcarter/.cd,2/.expanded=\the\numexpr\pgfkeysvalueof{/samcarter/2}+1}%
My array entry with the id 2 has now the value \pgfkeysvalueof{/samcarter/2}.
\end{document}


In principle this gives you everything that you need if it were not for the fact that you seem to want to employ foreach loops, which start groups and so local defintions do not work. (IMHO it would make a lot of sense to ask the maintainer(s) of pgf to add something along the lines of \pgfplotsforeachungrouped from pgfplots to pgffor.) Once we mess around with making the array indice global, we can add some more features like keeping track of the total, the lowest and largest array indices (so that we do not need to hardcode the number of colors, say). This is something along these lines. (It also allows you to create several arrays by changing the id etc.)


\documentclass{article}
\usepackage{pgffor}
\pgfmathsetseed{\number\pdfrandomseed}
\makeatletter
\pgfkeys{/pgf array/.cd,id/.initial=samcarter,
step/.code={%
\ifcsname pgfk@/pgf array/\pgfkeysvalueof{/pgf array/id}/#1\endcsname
%key #1 exists and is \csname pgfk@/pgf array/\pgfkeysvalueof{/pgf array/id}/#1\endcsname
\expandafter\xdef\csname pgfk@/pgf array/\pgfkeysvalueof{/pgf array/id}/#1\endcsname{%
\the\numexpr\csname pgfk@/pgf array/\pgfkeysvalueof{/pgf array/id}/#1\endcsname+1\relax
}%
\else
%key #1 does not exist
\expandafter\xdef\csname pgfk@/pgf array/\pgfkeysvalueof{/pgf array/id}/#1\endcsname{1}%
\fi
\ifcsname pgfk@/pgf array/\pgfkeysvalueof{/pgf array/id}/total\endcsname
%key total exists and is \csname pgfk@/pgf array/\pgfkeysvalueof{/pgf array/id}/total\endcsname
\expandafter\xdef\csname pgfk@/pgf array/\pgfkeysvalueof{/pgf array/id}/total\endcsname{%
\the\numexpr\csname pgfk@/pgf array/\pgfkeysvalueof{/pgf array/id}/total\endcsname+1\relax
}%
\else
%key total does not exist
\expandafter\xdef\csname pgfk@/pgf array/\pgfkeysvalueof{/pgf array/id}/total\endcsname{1}%
\fi
\ifcsname pgfk@/pgf array/\pgfkeysvalueof{/pgf array/id}/nmin\endcsname
\ifnum#1<\csname pgfk@/pgf array/\pgfkeysvalueof{/pgf array/id}/nmin\endcsname
\expandafter\xdef\csname pgfk@/pgf array/\pgfkeysvalueof{/pgf array/id}/nmin\endcsname{#1}%
\fi
\ifnum#1>\csname pgfk@/pgf array/\pgfkeysvalueof{/pgf array/id}/nmax\endcsname
\expandafter\xdef\csname pgfk@/pgf array/\pgfkeysvalueof{/pgf array/id}/nmax\endcsname{#1}%
\fi
\else
\expandafter\xdef\csname pgfk@/pgf array/\pgfkeysvalueof{/pgf array/id}/nmin\endcsname{#1}%
\expandafter\xdef\csname pgfk@/pgf array/\pgfkeysvalueof{/pgf array/id}/nmax\endcsname{#1}%
\fi
}
}
\makeatother
\begin{document}
\foreach \x in {1,...,10000}{%
\pgfmathrandominteger{\myran}{6}{28}%
\pgfkeys{/pgf array/step=\myran}%
}%

\foreach \x in {\pgfkeysvalueof{/pgf array/samcarter/nmin},%
\the\numexpr\pgfkeysvalueof{/pgf array/samcarter/nmin}+1,...,%
\pgfkeysvalueof{/pgf array/samcarter/nmax}}
{$\makebox[3em][l]{$\x$}:\pgfkeysvalueof{/pgf array/samcarter/\x},~ \pgfmathparse{\pgfkeysvalueof{/pgf array/samcarter/\x}/% \pgfkeysvalueof{/pgf array/samcarter/total}}f=\pgfmathresult$\par}
\end{document}


![Screen Shot 2020-09-03 at 2.35.21 PM.png](/image?hash=b91ab1942d3dcf7caf6e1ba0e6cd642f296c92d2e1e81c579a4d1179b4179336)

Enter question or answer id or url (and optionally further answer ids/urls from the same question) from

Separate each id/url with a space. No need to list your own answers; they will be imported automatically.