Return most common items in list I was wondering about the best way to return the most common items in a list.  So far the best way I could do it was:

//@param string $this-&gt;matched_ids_list = 1,11,12,11,12,
$this-&gt;matched_ids_list = "," . $this-&gt;matched_ids_list;
$this-&gt;ids_count = explode(",", $this-&gt;matched_ids_list);
$this-&gt;ids_count = array_unique($this-&gt;ids_count); //See below why this is done
foreach ($this-&gt;ids_count as $this-&gt;id) {
    $this-&gt;appearences[$this-&gt;id] = substr_count($this-&gt;matched_ids_list, ",{$this-&gt;id},");
    //[1] =&gt; 1, [11] =&gt; 2, [12] =&gt; 2
}
$this-&gt;most_appearences = max($this-&gt;appearences); //2
foreach ($this-&gt;appearences as $this-&gt;id =&gt; $this-&gt;times) {
    if ($this-&gt;times == $this-&gt;most_appearences) {
        $this-&gt;top_ids .= $this-&gt;id . ",";
    }
}
$this-&gt;top_ids = rtrim($this-&gt;top_ids, ",");
echo "tops = " . $this-&gt;top_ids;


It basically just works for 1,11,12,11,12, and returns 11,12, but it seems a bit overcomplicated. I've been at it for some time now.  Am I doing more steps than necessary, missing a built-in function or something?

I might be dealing with hundreds of ids, so performance is important.

Would this step:

foreach ($this-&gt;ids_count as $this-&gt;id) {
    $this-&gt;appearences[$this-&gt;id] = substr_count($this-&gt;matched_ids_list, ",{$this-&gt;id},");
    //[1] =&gt; 1, [11] =&gt; 2, [12] =&gt; 2
}


do more looping than necessary if array_unique wasn't used?

For instance, if ids_count was

[0] =&gt; 1, [1] =&gt; 11, [2] =&gt; 12, [3] =&gt; 11, [4] =&gt; 12


it would count how many times 11 and 12 appear on matched_ids_list twice. Instead, I use array_unique so ids_count is

[0] =&gt;, [1] =&gt; 1, [2] =&gt; 11, [3] =&gt; 12
Skip to the Dramatic Update for the best solution
I was curious how to do this myself, because I could clearly tell there had to be an easier way! I started from scratch and I think I've found exactly what this question is asking for.
I don't normally just rewrite code, but since the question asks the best way, I believe I'm obligated to share what I believe is the &quot;bets way&quot;.
$input = [1, 10, 11, 12, 11, 12, 18, 18];

$recorded = array_count_values($input);

arsort($recorded);

$output = [];

foreach ($recorded as $key =&gt; $value) {
    if ($value == max($recorded)) {
        array_push($output, $key);
    }
}

print_r($output);

I'll explain what's happening here:

We receive the input in $input
array_count_values() returns an array using the values of array as keys and their frequency in array as values. In our case, from $input.
arsort — Sort an array in reverse order and maintain index association
Loop over each pair in the newly sorted array. Create some variables to reference the current pair.
If the current value is equal to the largest value from $recorded
Add that key to the output!

And there we have it!
Update to increase performance
$input = [1, 10, 11, 12, 11, 12, 18, 18];

$recorded = array_count_values($input);

arsort($recorded);

$output = [];

$maximum = max($recorded);

foreach ($recorded as $key =&gt; $value) {
    if ($value == $maximum) {
        $output[] = $key;
    } else if ($value &lt; $maximum) {
        break;
    }
}

print_r($output);

We've stored the maximum so we aren't checking every iteration, and we're checking for a value less than the maximum so we can break out of the loop to prevent going through the whole array.
Dramatic Update
So, I completely missed the array_keys function, as pointed out by shudder. The newly improved code would look something like:
$input = [1, 10, 11, 12, 11, 12, 18, 18];

$recorded = array_count_values($input);

$output = array_keys($recorded, max($recorded));

print_r($output);

Crazy improvement compared to the OPs original code!