1
\$\begingroup\$

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.

\$\endgroup\$

3 Answers 3

2
\$\begingroup\$

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);
\$\endgroup\$
0
1
\$\begingroup\$

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];
\$\endgroup\$
5
  • \$\begingroup\$ Your code has an error see here codepad.org/IKn7JzfU \$\endgroup\$
    – Prakash
    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
    Aug 13, 2015 at 10:51
  • \$\begingroup\$ It does work here (where I used the latest available version): sandbox.onlinephpfunctions.com/code/… \$\endgroup\$
    – philonous
    Aug 13, 2015 at 10:58
  • \$\begingroup\$ see my question, I want to display U = 0, How to do this ??? \$\endgroup\$
    – Prakash
    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
    Aug 13, 2015 at 18:36
1
\$\begingroup\$

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

\$\endgroup\$
3
  • \$\begingroup\$ Your code has an error see here codepad.org/Ts2NZ5s9 \$\endgroup\$
    – Prakash
    Aug 14, 2015 at 5:25
  • \$\begingroup\$ Output shows D = 1, U = 1, I =1 But inside $array D = 3 & I = 2 \$\endgroup\$
    – Prakash
    Aug 14, 2015 at 6:01
  • \$\begingroup\$ Sorry for that, I updated my response with corrections \$\endgroup\$
    – kipelovets
    Sep 2, 2015 at 13:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.