开发者

array merging into multi dimensional array

开发者 https://www.devze.com 2023-04-03 11:28 出处:网络
I need a way to merge Array( [0] => Array ( [event_id] => 1 [time] => \'21:00pm\' [day] => \'Monday\'

I need a way to merge

Array(
  [0] => Array
     (
      [event_id] => 1
      [time] => '21:00pm'
      [day] => 'Monday'
     )
  [1] => Array
    (
      [event_id] => 2
      [time] => '18:00pm'
      [day] => 'Monday'
     )
  [2] => Array
    (
      [event_id] => 3
      [time] => '21:00pm'
      [day] => 'Tuesday'
     )
 )

into:

Array (
  [0] => Array
      (
          [event_id] => Array
                (
                 [0] => 1
                 [1] => 2
                )
          [time] => Array
               (
                 [0] => '21:00pm'
                 [1] => '1开发者_如何转开发8:00pm'
                )
          [day] => 'Monday'
      )
   [1] => Array
     (
          [event_id] => 3
          [time] => '21:00pm'
          [day] => 'Tuesday'
     )
)

So the new array is grouped by the day key and if the values are different between the merged arrays then the merged value becomes an array.


This should work.

$output = getMergedArray($input); // $input is your sample array

function getMergedArray($input_array) {
  $output_array = array();
  foreach ($input_array as $key => $value) {
    $event_id = $value['event_id'];
    $time = $value['time'];
    $day = $value['day'];
    $day_id = getDay($output_array, $day);
    if (count($output_array) > 0 && $day_id >= 0) {
      if (!is_array($output_array[$day_id]['event_id'])) {
        $output_array[$day_id]['event_id'] = array($output_array[$day_id]['event_id']);
        $output_array[$day_id]['time'] = array($output_array[$day_id]['time']);
      }
      array_push($output_array[$day_id]['event_id'],$event_id);
      array_push($output_array[$day_id]['time'],$time);
    } else {
      $output_array[] = $value;
    }
  }
  return $output_array;
}

function getDay($output_array, $day) {
  if (count($output_array) > 0)
    foreach($output_array as $key => $value)
      if ($value['day'] == $day)
        return $key;

  return -1;
}


I can't think of a built in function that will do this for you. I think you will have to loop through, group the events by day, then loop through the group and convert to the correct output format.

E.g.

This does not take into account the fact that the days may not always be in the same case, and also does not order the events by time, which may also be required.

function convert_event_array ($array) {

  // Declare the arrays we will use
  $temp = array(
    // Declare the day keys, so they appear in the right order in the output
    'Monday'=>array(),
    'Tuesday'=>array(),
    'Wednesday'=>array(),
    'Thursday'=>array(),
    'Friday'=>array(),
    'Saturday'=>array(),
    'Sunday'=>array()
  );
  $out = array();

  // Put events into temp array, grouped by day
  foreach ($array as $event) $temp[$event['day']][] = array('event_id'=>$event['event_id'],'time'=>$event['event_id']);

  // Convert grouped array to the correct format
  foreach ($temp as $day => $events) if (count($events)) {
    $index = count($out);
    foreach ($events as $event) {
      $out[$index]['event_id'][] = $event['event_id'];
      $out[$index]['time'][] = $event['time'];
    }
    $out[$index]['day'] = $day;
  }

  return $out;

}

print_r(convert_event_array($myInputArry));


I 'd propose this method which is fully generic and extensible:

// YOUR INPUT GOES HERE
$input = (...);

// Stage 1: group elements of the initial array into sub-arrays based on their 'day' key
$groupLambda = function($aggr, $val) {
                   $aggr[$val['day']][] = $val; return $aggr;
               };
$grouped = array_reduce($input, $groupLambda, array());

// Stage 2: for each "same day" group, make an array of values for each property
//          instead of an array of items with scalar properties
$coalesceLambda = function($group) {
                      $mapLambda = function($aggr, $val) {
                          foreach($val as $k => $v) {
                              if($k == 'day') continue;
                              $aggr[$k][] = $v; 
                          }
                          return $aggr;
                      };
                      return array_reduce($group, $mapLambda, array());
                  };
$coalesced = array_map($coalesceLambda, $grouped);

// Get the result
print_r($coalesced);

Advantages:

  1. There is only one magic value (the string "day"), which can be easily made into a variable and the whole thing factored out into a function (so you could reuse this function to perform the same transformation over any other property you might want to).
  2. Should be plenty fast due to using the built-in functions array_reduce and array_map instead of manually doing the same work in PHP.

Disadvantages:

  1. Requires PHP >= 5.3 due to the use of anonymous functions and the third parameter of array_reduce.
  2. Not very easy to understand (although code that does this kind of data massaging won't be too easy to visualize in any case).
0

精彩评论

暂无评论...
验证码 换一张
取 消