I want to count specific strings from array values
$array = array("report=D","report=D","report=D","report=I","report=I");
I am going to count the number of D
,U
& I
, as well as their meanings.
D = Delivered
U = Undelivered
I = Invalid
I am expecting an output of:
D = 3
U = 0
I = 2
First, I replace "report="
using str_replace()
, then array_filter
is used to count specific values.
<?php
$array = array(
"report=D","report=D","report=D","report=I","report=I"
);
$array = str_replace("report=","",$array);
function getting_u($n) { return $n == "U"; }
function getting_d($n) { return $n == "D"; }
function getting_i($n) { return $n == "I"; }
$result_of_u = array_filter($array, "getting_u");
$result_of_d = array_filter($array, "getting_d");
$result_of_i = array_filter($array, "getting_i");
print_r($result_of_u);
print_r($result_of_d);
print_r($result_of_i);
echo "Count of U = ".count($result_of_u);
echo "\n";
echo "Count of D = ".count($result_of_d);
echo "\n";
echo "Count of I = ".count($result_of_i);
?>
See a working code here.
The code seems to work fine for me, but I'm concerned whether this is the correct/best method of procedure.
I am also unsure if my code contains any strange behaviour or present/future problems.
3 Answers 3
As I can't comment, the philonus's answer is the clearer and best for me, if you want to display zero you can do this, initializing the stats array:
$input = array(
"report=D","report=D","report=D","report=I","report=I"
);
$stats = array(
'U' => 0,
'D' => 0,
'I' => 0,
);
foreach($input as $value) {
$types = explode('=', $value);
$stats[$types[1]]++;
}
print_r($stats);
I am not really an expert in PHP, but this can certainly be done a bit easier. First of all it seems as if you would need to iterate over the input array only once (while the ordering of the array does not matter). Hence you can use a foreach($array_to_work_on, $single_value)
construct and do all the logic therein.
So the first thing to do is to split each value. You can use explode
which takes as a first argument the string where the input value should be split and as a second the input itself. Since we are not interested in the first part we take only the second one (with the index 1
).
Then you can make use of the "array" (or rather dictionary) data structure provided by PHP: Whenever we encounter an unseen "key" we add a new entry to the dictionary and save "1" as the number of already counted elements. In the other case (if we have already seen this key) we increment it by one.
So here is the code:
$input = array(
"report=D","report=D","report=D","report=I","report=I"
);
$stats = array();
foreach($input as $value) {
$type = explode('=', $value)[1];
$stats[$type] = array_key_exists($type,$stats) ? $stats[$type] + 1 : 1;
}
print_r($stats);
Note that now you also sum up also the frequency of other keys, not only "I", "O", and "U", which makes it easier to maintain or to extend.
Edit: As has been pointed out in the comments, one cannot use "function array dereferencing", i.e. $type = explode('=', $value)[1];
in older PHP versions. So the solution in this case would be to introduce a temporary variable:
$parts = explode('=', $value);
$type = $parts[1];
-
\$\begingroup\$ Your code has an error see here codepad.org/IKn7JzfU \$\endgroup\$Prakash– Prakash2015年08月13日 10:32:48 +00:00Commented Aug 13, 2015 at 10:32
-
2\$\begingroup\$ The
explode('=', $value)[1];
is not valid in PHP 5.3, but it's ok in PHP 5.4. php.net/manual/en/migration54.new-features.php \$\endgroup\$arvidj– arvidj2015年08月13日 10:51:32 +00:00Commented Aug 13, 2015 at 10:51 -
\$\begingroup\$ It does work here (where I used the latest available version): sandbox.onlinephpfunctions.com/code/… \$\endgroup\$philonous– philonous2015年08月13日 10:58:43 +00:00Commented Aug 13, 2015 at 10:58
-
\$\begingroup\$ see my question, I want to display U = 0, How to do this ??? \$\endgroup\$Prakash– Prakash2015年08月13日 15:04:33 +00:00Commented Aug 13, 2015 at 15:04
-
\$\begingroup\$ You can check if the key exists in the array. If it does not then you have zero elements for this key. \$\endgroup\$philonous– philonous2015年08月13日 18:36:34 +00:00Commented Aug 13, 2015 at 18:36
After calling str_replace
to strip report=
part you can use array_count_values
function:
<?php
$array = array(
'report=D','report=D','report=D','report=I','report=I'
);
$array = str_replace('report=', '', $array);
$defaults = array('U' => 0, 'D' => 0, 'I' => 0);
$counts = array_merge(
$defaults,
array_count_values($array)
);
echo 'Count of U = '.$counts['U']."\n";
echo 'Count of D = '.$counts['D']."\n";
echo 'Count of I = '.$counts['I']."\n";
Also I can't help but mention that this array('report=*',...)
format seems really odd and unmaintainable.
Edit: Added array_merge
to prevent 'Undefined offset' error
-
\$\begingroup\$ Your code has an error see here codepad.org/Ts2NZ5s9 \$\endgroup\$Prakash– Prakash2015年08月14日 05:25:34 +00:00Commented Aug 14, 2015 at 5:25
-
\$\begingroup\$ Output shows D = 1, U = 1, I =1 But inside $array D = 3 & I = 2 \$\endgroup\$Prakash– Prakash2015年08月14日 06:01:56 +00:00Commented Aug 14, 2015 at 6:01
-
\$\begingroup\$ Sorry for that, I updated my response with corrections \$\endgroup\$kipelovets– kipelovets2015年09月02日 13:58:56 +00:00Commented Sep 2, 2015 at 13:58