Aloysia de Argenteuil
Aloysia de Argenteuil

Reputation: 902

How to create an array from another array that counts how many times a particular value occurs using php?

I have an array from which I would like to extract some values in a particular form.

    $array1 = array(
            array("techArea01",1995),
            array("techArea03",1996),
            array("techArea01",1995),
            array("techArea09",1998),
            array("techArea09",1995),
            array("techArea02",1997),
            array("techArea01",1995),
            array("techArea02",1999),
            array("techArea09",1995)
        );

But first I sort it by key = 0 and key = 1.

    //Select indexes to sort array.
    $sort = array();
    foreach($array1 as $k=>$v) {
        $sort['0'][$k] = $v['0']; //Sort by tech area.
        $sort['1'][$k] = $v['1']; //Sort by priority date.
    }
    //These variables will be used independently below:
    $sortedByTechArea = $array1;
    $sortedByPriorityDate = $array1;

I sort first by tech area and exclude double entries:

    //Sort by tech_area asc
    array_multisort($sort['0'], SORT_ASC,$sortedByTechArea);
    $sortedByTechArea = $sortedByTechArea;

    //Exclude duplicated tech areas entries from array.
    $excludeDoubleEntryInTechArea = array();
    foreach ($sortedByTechArea as &$value) {
        if (!isset($excludeDoubleEntryInTechArea[$value['0']]))
        $excludeDoubleEntryInTechArea[$value['0']] =& $value;
    }
    $sortedByTechArea = array_values($excludeDoubleEntryInTechArea);

it give us following result:

$TechAreaWithoutDoubles:
Array
(
[0] => Array
    (
        [0] => techArea01
        [1] => 1995
    )

[1] => Array
    (
        [0] => techArea02
        [1] => 1997
    )

[2] => Array
    (
        [0] => techArea03
        [1] => 1996
    )

[3] => Array
    (
        [0] => techArea09
        [1] => 1995
    )

)

And finally I extract the unique tech areas:

    $techArea = '';
    foreach ($sortedByTechArea as $subArrayTechArea) {
        $techArea .= "$subArrayTechArea[0]".',<br />';
    }
    echo 'Ordered list of tech areas:<br />';
    echo $techArea,'</pre>';

And here the result:

Ordered list of tech areas:
techArea01,
techArea02,
techArea03,
techArea09,

To the years I do something similar and in the end I have following result:

Ordered list of years:
1995,
1996,
1997,
1998,
1999,

So far, so good, but what I really want is to know how many times a tech area occurs in a year. So I do the following:

echo '<pre>How many tech areas per year exist?<br />';
    //Count of tech area per year.
    $result = array();
    foreach ($array1 as $part) {
        $key = implode(', ', $part);
        if( ! array_key_exists ($key, $result)) {
            $result[$key] = 0;
        }
        $result[$key] = $result[$key] + 1;
    }
    foreach ($result as $key => $value) {
        $count[] = $key.",".$value;
    }

    sort($count);
print_r($count);
echo '</pre>';

With that we have following result:

How many tech areas per year exist?
Array
(
    [0] => techArea01, 1995,3
    [1] => techArea02, 1997,1
    [2] => techArea02, 1999,1
    [3] => techArea03, 1996,1
    [4] => techArea09, 1995,2
    [5] => techArea09, 1998,1
)

So we know, for example, how many times tech area 01 occurs in 1995. The problem is that it doesn't tell us explicit when a tech area doesn't occur. As a matter of fact I'm searching a way to create following matrix:

     techArea01 | techArea02 | techArea03 | techArea09
1995      3     |      0     |      0     |      2
1996      0     |      0     |      1     |      0
1997      0     |      1     |      0     |      0
1998      0     |      0     |      0     |      1
1999      0     |      1     |      0     |      0

Or to be more exact, following array would solve the problem:

$finalArray = array(
                    array(1995, 3, 0, 0, 2),
                    array(1996, 0, 0, 1, 0),
                    etc.
                    array(1999, 0, 1, 0, 0)
              );

I thought I could use the ordered list that I create above or something similar to create the array, but I don't know how to insert the "zeros".

Is there any more elegant solution to do this? Or maybe someone has another idea to get the values direct from the original array?

I would appreciate any help.

Upvotes: 0

Views: 53

Answers (2)

i alarmed alien
i alarmed alien

Reputation: 9520

I would get the values directly from the original array like so:

foreach ($array1 as $ta) {
    // $ta[0] is tech area, $ta[1] is year.
    // index by tech area and then year.
    // the accumulator will count the number per tech area per year
    $finalArray[ $ta[0] ][ $ta[1] ]++;
    // keep an array of years
    $years[ $ta[1] ]++;
}

If you just want the results in a data structure, you could do this to ensure that all tech areas have values for all years:

foreach ($years as $y => $z) {
    foreach ($finalArray as $ta => &$value) {
        if (! array_key_exists($y, $value)) {
            $value[$y] = 0;
        }
    }
}

If you're printing out the results as a table, you could do the following:

// sort arrays by key
ksort($finalArray);
ksort($years);

// let's say we're printing out a table.
echo "<table>\n<thead><tr><th>Year</th>";

// add the tech areas
foreach ($finalArray as $ta => $value) {
    echo '<th>' . $ta . '</th>';
}
echo "</tr></thead>\n<tbody>";

// now add the data
foreach ($years as $y => $z) {
    echo '<tr><td>' . $y . '</td>';
    foreach ($finalArray as $ta => $value) {
        echo '<tr>';
        if (array_key_exists($y, $value)) {
            echo '<td>' . $value[$y] . '</td>';
        } else {
            echo '<td>0</td>';
        }
    }
    echo "</tr>\n";
}
echo '</tbody></table>';

Upvotes: 0

ins0
ins0

Reputation: 3928

try this

 $array1 = array(
            array("techArea01",1995),
            array("techArea03",1996),
            array("techArea01",1995),
            array("techArea09",1998),
            array("techArea09",1995),
            array("techArea02",1997),
            array("techArea01",1995),
            array("techArea02",1999),
            array("techArea09",1995)
        );

$sorted = array();
$areas = array();
array_walk($array1, function($v) use (&$sorted, &$areas){
   if( !isset($sorted[$v[1]]) )
       $sorted[$v[1]] = array();
   $sorted[$v[1]][] = $v[0];
   $areas[] = $v[0];
});

// filter areas
$areas = array_unique($areas);
sort($areas);

// sort year
ksort($sorted);


echo '----' . implode(' ,', $areas) . "\r\n";
foreach($sorted as $year => $data)
{
   echo $year . ' - ';
   $count = array_count_values($data);

   foreach($areas as $area)
   {  
      if( !isset($count[$area]))
      {
          echo '0,';
      } else {
          echo $count[$area].',';
      }
   }
   echo "\r\n";
}

gives

----techArea01 ,techArea02 ,techArea03 ,techArea09
1995 - 3,0,0,2,
1996 - 0,0,1,0,
1997 - 0,1,0,0,
1998 - 0,0,0,1,
1999 - 0,1,0,0,

Upvotes: 1

Related Questions