What collection in PHP to count and order occurencies

Viewed 88

Using PHP 7.3/7.4 I'd like to use/create a key-value collection. I'd like to push many time the same key. Each time the value should increment (the first time the value is 1). And at the end, I need to get the key-value pairs ordered by values.

For example

$somecollection = ???
$somecollection->add('hello')
$somecollection->add('bye')
$somecollection->add('hello')
$somecollection->add('John')
$somecollection->add('bye')
$somecollection->add('hello')

should return

$ordered = $somecollection->ordered()
dump($ordered) --> ['hello' -> 3, 'bye' -> 2, 'john' ->1]

Does that allready exist?

3 Answers

Building this into a class will allow you to create counters as you need. This has a private variable which stores the count for each time you call inc() (as it's an increment rather than add()).

The ordered() method first sorts the counters (using arsort to keep the keys in line)...

class Counter {
    private $counters = [];
    
    public function inc ( string $name ) : void {
        $this->counters[$name] = ($this->counters[$name] ?? 0) + 1;
    }
    
    public function ordered() : array {
        arsort($this->counters);
        return $this->counters;
    }
}

so

$counter = new Counter();
$counter->inc("first");
$counter->inc("a");
$counter->inc("2");
$counter->inc("a");

print_r($counter->ordered());

gives...

Array
(
    [a] => 2
    [first] => 1
    [2] => 1
)

There is a native PHP function for this. See array_count_values().

Just add a value by pushing it into a normal array:

$values = [];

$values[] = 'hello';
$values[] = 'bye';
$values[] = 'hello';
$values[] = 'John';
$values[] = 'hello';
$values[] = 'bye';

// Count the unique instances in the array
$totals = array_count_values($values);

// If you want to sort them
asort($totals);

// If you want to sort them reversed
arsort($totals);

Resulting $totals array will be:

Array
(
    [hello] => 3
    [bye] => 2
    [John] => 1
)

You can perform this via:

function count_array_values($my_array, $match) 
{
    $count = 0; 
    foreach ($my_array as $key => $value) 
    { 
        if ($value == $match) 
        { 
            $count++; 
        } 
    }    
    return $count; 
} 
$array = ["hello","bye","hello","John","bye","hello"];
$output =[];

foreach($array as $a){
    $output[$a] = count_array_values($array, $a); 
}
arsort($output);
print_r($output);

You will get output like

Array ( [hello] => 3 [bye] => 2 [John] => 1 )
Related