0

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.

2 Answers 2

1

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,
Sign up to request clarification or add additional context in comments.

1 Comment

Just substituted the echos with variables and the code works like a charm to me. Thanks!
0

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>';

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.