(PHP 4, PHP 5)
array_count_values — Zählt die Werte eines Arrays
array_count_values() gibt ein Array zurück, in dem die Werte des Arrays input als Schlüssel, und die Häufigkeit ihres Auftretens als Werte angegeben sind.
Das Array mit den zu zählenden Werten
Gibt ein assoziatives Array mit den Werten aus input als Schlüsseln und der Anzahl als Werten zurück.
Beispiel #1 array_count_values()-Beispiel
<?php
$array = array(1, "hello", 1, "world", "hello");
print_r(array_count_values($array));
?>
Das oben gezeigte Beispiel erzeugt folgende Ausgabe:
Array ( [1] => 2 [hello] => 2 [world] => 1 )
Hy,
i had a problem which was associated with the array_count_values function, but did not solve my problem realy well so i made a function by my self and maybe it can help also someone else.
The problem was that i had a table like this:
CL PRODNUM QN DATE
1 4221110030 2 10.12.2010
2 4221110031 1 10.12.2010
3 5241110002 1 10.12.2010
3 5241110003 1 11.12.2010
3 5241110001 2 11.12.2010
3 6241110001 1 11.12.2010
1 2231110999 1 10.12.2010
1 2231110999 1 11.12.2010
(it go's on and on ... )
And i wanted to calculate for every unique date how much the quantity of the specific CL is.
For example the result should be like this:
10.12.2010: [1] -> 3
10.12.2010: [2] -> 1
10.12.2010: [3] -> 1
11.12.2010: [1] -> 1
11.12.2010: [2] -> 0
11.12.2010: [3] -> 4
So, i had to make a function which should look for unique values of a date and then for that date get the quantity of uniqe CL's.
For note: i put all the values of the table into an array:
<?php
$a = array();
$a['cl'] = 1;
$a['prodnum'] = '4221110030';
$a['qn'] = '2';
$a['date'] = '10.12.2010';
?>
The function looks like this:
<?php
function csav( $array, $distinctV, $searchInV, $sumValue ){
#result array
$result = array();
#finding the unique dates
$array1 = array_unique($array[$searchInV]);
$array2 = array();
$unique1 = array_merge($array2, $array1);
#finding the unique CL's
$array3 = array_unique($array[$distinctV]);
$array4 = array();
$unique2 = array_merge($array4, $array3);
#for statements through the unique dates
for($k = 0; $k < count($unique1); $k++){
for($i = 0; $i < count($unique2); $i++){
$sum = 0;
for($j = 0; $j < count($array[$distinctV]); $j++){
if($array[$distinctV][$j] == $unique2[$i] and $array[$searchInV][$j] == $unique1[$k])
$sum += $array[$sumValue][$j];
}
$result[$unique1[$k]][$unique2[$i]] = $sum;
}
}
return $result;
}
?>
The use of function has to be like this:
<?php
$result = csav($a, 'cl', 'date', 'qn');
print_r($result);
?>
And the result looks like this:
Array ( [2010-12-10] => Array ( [1] => 14 [2] => 17 [3] => 4 ) [2010-12-13] => Array ( [1] => 13 [2] => 17 [3] => 4 ) [2010-12-14] => Array ( [1] => 13 [2] => 17 [3] => 4 ) [2010-12-15] => Array ( [1] => 14 [2] => 17 [3] => 4 ) [2010-12-16] => Array ( [1] => 14 [2] => 17 [3] => 2 ) )
This is it.
Hope it helps someone.
Here is a Version with one or more arrays, which have similar values in it:
Use $lower=true/false to ignore/set case Sensitiv.
<?php
$ar1[] = array("red","green","yellow","blue");
$ar1[] = array("green","yellow","brown","red","white","yellow");
$ar1[] = array("red","green","brown","blue","black","yellow");
#$ar1= array("red","green","brown","blue","black","red","green"); // Possible with one or multiple Array
$res = array_icount_values ($ar1);
print_r($res);
function array_icount_values($arr,$lower=true) {
$arr2=array();
if(!is_array($arr['0'])){$arr=array($arr);}
foreach($arr as $k=> $v){
foreach($v as $v2){
if($lower==true) {$v2=strtolower($v2);}
if(!isset($arr2[$v2])){
$arr2[$v2]=1;
}else{
$arr2[$v2]++;
}
}
}
return $arr2;
}
/*
Will print:
Array
(
[red] => 3
[green] => 3
[yellow] => 4
[blue] => 2
[brown] => 2
[white] => 1
[black] => 1
)
*/
?>
byron at byronrode dot co dot za, here are some benchmarks.
<?php
$haystack = Array();
for ($i = 0; $i < 1000000; $i++) {
$haystack[] = rand(1, 2000);
}
$needle = rand(1, 2000);
echo "__array_count_values()__\n";
$start = microtime(true);
$startmem = memory_get_usage();
$counts = array_count_values($haystack);
$mem = memory_get_usage()-$startmem;
echo 'Count:'.$counts[$needle]."\n";
echo 'Time:'.(microtime(true) - $start)."\n";
echo 'Memory:'.$mem."\n\n";
echo "__array_keys()__\n";
$start = microtime(true);
$startmem = memory_get_usage();
$keys = array_keys($haystack, $needle);
$mem = memory_get_usage()-$startmem;
echo 'Count:'.count($keys)."\n";
echo 'Time:'.(microtime(true) - $start)."\n";
echo 'Memory:'.$mem."\n\n";
echo '__$needle_array[]__'."\n";
$start = microtime(true);
$startmem = memory_get_usage();
$x = count($haystack);
for($i = 0; $i < $x; $i++){
if($haystack[$i] == $needle){
$needle_array[] = $haystack[$i];
}
}
$mem = memory_get_usage()-$startmem;
$number_of_instances = count($needle_array);
echo 'Count:'.$number_of_instances."\n";
echo 'Time:'.(microtime(true) - $start)."\n";
echo 'Memory:'.$mem."\n\n";
echo '__$number_of_instances++__'."\n";
$start = microtime(true);
$startmem = memory_get_usage();
$x = count($haystack);
$number_of_instances = 0;
for($i = 0; $i < $x; $i++){
if($haystack[$i] == $needle){
$number_of_instances++;
}
}
$mem = memory_get_usage()-$startmem;
echo 'Count:'.$number_of_instances."\n";
echo 'Time:'.(microtime(true) - $start)."\n";
echo 'Memory:'.$mem."\n\n";
?>
[www]mytemp$ php array_count_test.php
__array_count_values()__
Count:515
Time:0.0607650279999
Memory:120328
__array_keys()__
Count:515
Time:0.0869138240814
Memory:33016
__$needle_array[]__
Count:515
Time:0.259949922562
Memory:24792
__$number_of_instances++__
Count:515
Time:0.258481025696
Memory:0
However, when you use an array of strings by calling md5(rand(1, 2000)), the performance boosts become less significant:
__array_count_values()__
Count:499
Time:0.491794109344
Memory:184328
__array_keys()__
Count:499
Time:0.36399102211
Memory:30072
__$needle_array[]__
Count:499
Time:0.568728923798
Memory:22104
__$number_of_instances++__
Count:499
Time:0.574353933334
Memory:0
Results are similar for string->string haystacks with foreach traversal.
Yet Another case-insensitive version of array_count_values()
<?php
$ar = array('J. Karjalainen', 'J. Karjalainen', 60, '60', 'J. Karjalainen', 'j. karjalainen', 'Fastway', 'FASTWAY', 'Fastway', 'fastway', 'YUP');
$ar = array_count_values(array_map('strtolower', $ar));
?>
I am building a script for a quiz, and could not find any answers to count the number of times a value was repeated in an array, and came up with the following function.
<?php
// Answers Array
$array = array('a', 'b', 'a', 'a', 'c', 'a', 'd', 'a', 'c', 'd');
// Start Count Function
function count_repeat_values($needle, $haystack){
$x = count($haystack);
for($i = 0; $i < $x; $i++){
if($haystack[$i] == $needle){
$needle_array[] = $haystack[$i];
}
}
$number_of_instances = count($needle_array);
return $number_of_instances;
}
echo count_repeat_values('a', $array);
// will return the value 5
?>
But after writing the function, I happened to stroll upon array_count_values() which I had completely forgotten about.
I know that i could get the value by doing this:
<?php
$array = array('a', 'b', 'a', 'a', 'c', 'a', 'd', 'a', 'c', 'd');
$answer = array_count_values($array);
echo $answer['a']
?>
Would be interesting to see which version works quicker...
<?
function array_icount_values($array) {
$ret_array = array();
foreach($array as $value) $ret_array[strtolower($value)]++;
return $ret_array;
}
$ar = array('J. Karjalainen', 'J. Karjalainen', 60, '60', 'J. Karjalainen', 'j. karjalainen', 'Fastway', 'FASTWAY', 'Fastway', 'fastway', 'YUP');
$ar = array_icount_values($ar);
?>
this prints:
Array
(
[j. karjalainen] => 4
[60] => 2
[fastway] => 4
[yup] => 1
)
I couldn't find a function for counting the values with case-insensitive matching, so I wrote a quick and dirty solution myself:
<pre><?php
function array_icount_values($array) {
$ret_array = array();
foreach($array as $value) {
foreach($ret_array as $key2 => $value2) {
if(strtolower($key2) == strtolower($value)) {
$ret_array[$key2]++;
continue 2;
}
}
$ret_array[$value] = 1;
}
return $ret_array;
}
$ar = array('J. Karjalainen', 'J. Karjalainen', 60, '60', 'J. Karjalainen', 'j. karjalainen', 'Fastway', 'FASTWAY', 'Fastway', 'fastway', 'YUP');
$ar2 = array_count_values($ar); // Normal matching
$ar = array_icount_values($ar); // Case-insensitive matching
print_r($ar2);
print_r($ar);
?></pre>
This prints:
Array
(
[J. Karjalainen] => 3
[60] => 2
[j. karjalainen] => 1
[Fastway] => 2
[FASTWAY] => 1
[fastway] => 1
[YUP] => 1
)
Array
(
[J. Karjalainen] => 4
[60] => 2
[Fastway] => 4
[YUP] => 1
)
I don't know how efficient it is, but it seems to work. Needed this function in one of my scripts and thought I would share it.
Scratch that, I did something stupid. Here is a better function.
<?php
function array_enumerate_keys($array)
{
$index = 0;
$enumerated = array();
$values = array_values($array);
$keys = array_keys($array);
for($index = 0; $index < count($array); $index++)
{
$iteration;
for($iteration = 0; $iteration < $values[$index]; $iteration++)
{
$enumerated = array_merge($enumerated, array($keys[$index]));
}
}
return $enumerated;
}
?>
A possible inverse function for array_count_values
<?php
function array_enumerate_keys($array)
{
$index;
$enumerated;
$values = array_values($array);
$keys = array_keys($array);
for($index = 0; $index < count($array); $index++)
{
$iteration;
for($iteration = 0; $iteration < $values[$index]; $iteration++)
{
$enumerated .= $keys[$index] . ',';
}
}
return explode(',', $enumerated);
}
?>
alwaysdrunk's comment only works if you can trust the client web browser. Using this function doesn't validate that every necessary field exists -- only that every field that was submitted has a value in it. Thus if an attacker wished to force a null value into one of the fields, he could (rather easily) construct a modified form without the field and submit THAT.
Besides, you really ought to be validating each field anyway if you're taking user input.
if you have too many values in $_POST,$_GET array that needs to be controlled with isset() in oreder to understand the form is filled completely and have no empty text boxes.
you can try this,it saves time.
<?
$n = array_count_values($_POST);
if (!isset($n[''])) {
echo "The form is filled completely";
}
else
{ die("Please fill the form comlpetely"); }
//tested in php 5
?>
I find a very simple solution to count values in multidimentional arrays (example for 2 levels) :
foreach ($array as $a) {
foreach ($a as $b) {
$count_values[$b]++;
}
}
my solution for count on multidimentional arrays.
<?php
for($i = 0; $i < count($array); $i++) {
$detail = explode("|", $array[$i]);
echo "$i - $detail[0] - $detail[1]<br><br>";
if($detail[1] == '1') { $wieoft1 = $wieoft1 +=1; }
if($detail[1] == '2') { $wieoft2 = $wieoft2 +=1; }
if($detail[1] == '3') { $wieoft3 = $wieoft3 +=1; }
}
echo ". $wieoft1 : $wieoft2 : $wieoft3";
?>
looks not pretty fine yet works great for me.
make it bigger for your own.
array_count_values returns the number of keys if empty(value). I expected array_count_values to return 0 for empty values.
Array looks like:
Array
(
[459] =>
[543] =>
[8959] =>
[11273] =>
)
array_count_values returns:
Array
(
[] => 4
)
count(array_count_values(array)) does thus not report there are no values (other than empty) in the array.
I therefore check:
$arrFoo=array_count_values($arrBar);
if(isset($arrFoo[""]) $allempty=count($arrBar)==$arrFoo[""];
if(!$allempty)
//process the array
else
//no need to work on the array
I fount a solution for the count of array elements in the sense of array_count_values, but i was not able to use the function array_count_values itself because it does not say me if arrays exists in the given array, so i had to use a foreach loop and a little bit of recursivity ;)
<?php
function array_count_values_multidim($a,$out=false) {
if ($out===false) $out=array();
if (is_array($a)) {
foreach($a as $e)
$out=array_count_values_multidim($e,$out);
}
else {
if (array_key_exists($a,$out))
$out[$a]++;
else
$out[$a]=1;
}
return $out;
}
?>
array_count_values function does not work on multidimentional arrays.
If $score[][] is a bidimentional array, the command
"array_count_values ($score)" return the error message "Warning: Can only count STRING and INTEGER values!".
You might use serialize() to serialize your objects before analyzing their frequency. :)
suggested plan of attack:
<pre>
<?
class MyObject {
function MyObject($t = 'none')
{
$this->$myTag = $t;
}
}
$myArray = array();
for ($i = 1 ; $i < 11 ; $i++)
{
$myobj = new MyObject( str_pad('n', $i, 'x') );
$myArray[ $myobj->$myTag ] = $myobj;
}
print_r( array_count_values(array_keys($myArray)) );
?>
to sum up:
assuming each instance of an object you create has some sort of tag, e.g.,
$this->$myTag=get_class($this)
..you should be set. objects dont have value to compare the way strings and integers do, so, $myTag's value is arbitrary.
This does not works with objects. If you have an array filled with objects, you can not count them.
Example:
<?php
$myArray = array();
for ($i = 0 ; $i < 10 ; $i++)
{
$myObject = new MyObject();
$myArray[$i] = $myObject;
}
echo (array_count_values($myArray));
?>
This gives you:
Warning: Can only count STRING and INTEGER values...
Found no solution for this yet...