Reputation: 6031
I have an array in PHP:
array (size=xxx)
0 =>
array (size=9)
'cat' => string 'FIRST CAT'
'dur' => string '10'
'type' => string 'Type description 10'
'start' => string '00:00'
'end' => string '01:00'
'desc' => string 'Event description 10-1'
'price' => string 'xxx'
'extra' => string 'yyy'
1 =>
array (size=9)
'cat' => string ''
'dur' => string ''
'type' => string ''
'start' => string '01:00'
'end' => string '02:00'
'desc' => string 'Event description 10-2'
'price' => string ''
'extra' => string ''
2 =>
array (size=9)
'cat' => string ''
'dur' => string ''
'type' => string ''
'start' => string '02:00'
'end' => string '03:00'
'desc' => string 'Event description 10-3'
'price' => string ''
'extra' => string ''
3 =>
array (size=9)
'cat' => string ''
'dur' => string '20'
'type' => string 'Type description 20'
'start' => string '00:00'
'end' => string '01:00'
'desc' => string 'Event description 20-1'
'price' => string 'xxx'
'extra' => string 'yyy'
4 =>
array (size=9)
'cat' => string ''
'dur' => string ''
'type' => string ''
'start' => string '01:00'
'end' => string '02:00'
'desc' => string 'Event description 20-2'
'price' => string ''
'extra' => string ''
5 =>
array (size=9)
'cat' => string ''
'dur' => string ''
'type' => string 'Type description 21'
'start' => string '00:00'
'end' => string '01:00'
'desc' => string 'Event description 21-1'
'price' => string 'xxx'
'extra' => string 'yyy'
6 =>
array (size=9)
'cat' => string ''
'dur' => string ''
'type' => string ''
'start' => string '01:00'
'end' => string '02:00'
'desc' => string 'Event description 21-2'
'price' => string ''
'extra' => string ''
7 =>
array (size=9)
'cat' => string 'SECOND CAT'
'dur' => string '10'
'type' => string 'Type description 100'
'start' => string '00:00'
'end' => string '01:00'
'desc' => string 'Event description 100-1'
'price' => string 'xxx'
'extra' => string 'yyy'
8 =>
array (size=9)
'cat' => string ''
'dur' => string ''
'type' => string ''
'start' => string '01:00'
'end' => string '02:00'
'desc' => string 'Event description 100-2'
'price' => string ''
'extra' => string ''
9 =>
array (size=9)
'cat' => string ''
'dur' => string '20'
'type' => string 'Type description 200'
'start' => string '00:00'
'end' => string '01:00'
'desc' => string 'Event description 200-1'
'price' => string 'xxx'
'extra' => string 'yyy'
10 =>
array (size=9)
'cat' => string ''
'dur' => string ''
'type' => string ''
'start' => string '01:00'
'end' => string '02:00'
'desc' => string 'Event description 200-2'
'price' => string ''
'extra' => string ''
11 =>
array (size=9)
'cat' => string ''
'dur' => string ''
'type' => string 'Type description 210'
'start' => string '00:00'
'end' => string '01:00'
'desc' => string 'Event description 210-1'
'price' => string 'xxx'
'extra' => string 'yyy'
etc...
I need to group this array first by cat
, then by dur
, then type
. This type
array would have two strings - price
and extra
and another array which would consist of all the events data - start
, end
and desc
. Final array outline (based on example above) should look like this:
'FIRST CAT' // 'cat'
'10' // 'dur'
'Type description 10', 'xxx', 'yyy' // 'type', 'price', 'extra'
(array of events)
'00:00', '01:00', 'Event description 10-1' // 'start', 'end', 'desc'
'01:00', '02:00', 'Event description 10-2' // 'start', 'end', 'desc'
'02:00', '03:00', 'Event description 10-3' // 'start', 'end', 'desc'
'20'
'Type description 20', 'xxx', 'yyy'
(array of events)
'00:00', '01:00', 'Event description 20-1'
'01:00', '02:00', 'Event description 20-2'
'Type description 21', 'xxx', 'yyy'
(array of events)
'00:00', '01:00', 'Event description 21-1'
'01:00', '02:00', 'Event description 21-2'
'SECOND CAT'
'10'
'Type description 100', 'xxx', 'yyy'
(array of events)
'00:00', '01:00', 'Event description 100-1'
'01:00', '02:00', 'Event description 100-2'
'20'
'Type description 200', 'xxx', 'yyy'
(array of events)
'00:00', '01:00', 'Event description 200-1'
'01:00', '02:00', 'Event description 200-2'
'Type description 210', 'xxx', 'yyy'
(array of events)
'00:00', '01:00', 'Event description 210-1'
'01:00', '02:00', 'Event description 210-2'
What would be the simplest way to convert my existing array to the one I need in the end?
Upvotes: -1
Views: 304
Reputation: 47864
To preserve accessibility to relatable data while traversing the input array, I'm using reference variables because cat
and dur
values may be empty in some rows. Demo
$result = [];
foreach ($array as $row) {
if ($row['cat']) {
// kill prior cat reference when new cat is non-empty
unset($catRef);
// start a new cat reference
$result[$row['cat']] =& $catRef;
}
if ($row['dur']) {
// kill prior dur reference when new dur is non-empty
unset($durEventsRef);
// push event-shared data into dur subarray
$catRef[$row['dur']] = [
'type' => $row['type'],
'price' => $row['price'],
'extra' => $row['extra'],
'events' => [],
];
// start a new dur-events reference
$catRef[$row['dur']]['events'] =& $durEventsRef;
}
// push data into dur-event reference
$durEventsRef[] = [
'start' => $row['start'],
'end' => $row['end'],
'desc' => $row['desc'],
];
}
var_export($result);
Output:
array (
'FIRST CAT' =>
array (
10 =>
array (
'type' => 'Type description 10',
'price' => 'xxx',
'extra' => 'yyy',
'events' =>
array (
0 =>
array (
'start' => '00:00',
'end' => '01:00',
'desc' => 'Event description 10-1',
),
1 =>
array (
'start' => '01:00',
'end' => '02:00',
'desc' => 'Event description 10-2',
),
2 =>
array (
'start' => '02:00',
'end' => '03:00',
'desc' => 'Event description 10-3',
),
),
),
20 =>
array (
'type' => 'Type description 20',
'price' => 'xxx',
'extra' => 'yyy',
'events' =>
array (
0 =>
array (
'start' => '00:00',
'end' => '01:00',
'desc' => 'Event description 20-1',
),
1 =>
array (
'start' => '01:00',
'end' => '02:00',
'desc' => 'Event description 20-2',
),
2 =>
array (
'start' => '00:00',
'end' => '01:00',
'desc' => 'Event description 21-1',
),
3 =>
array (
'start' => '01:00',
'end' => '02:00',
'desc' => 'Event description 21-2',
),
),
),
),
'SECOND CAT' =>
array (
10 =>
array (
'type' => 'Type description 100',
'price' => 'xxx',
'extra' => 'yyy',
'events' =>
array (
0 =>
array (
'start' => '00:00',
'end' => '01:00',
'desc' => 'Event description 100-1',
),
1 =>
array (
'start' => '01:00',
'end' => '02:00',
'desc' => 'Event description 100-2',
),
),
),
20 =>
array (
'type' => 'Type description 200',
'price' => 'xxx',
'extra' => 'yyy',
'events' =>
array (
0 =>
array (
'start' => '00:00',
'end' => '01:00',
'desc' => 'Event description 200-1',
),
1 =>
array (
'start' => '01:00',
'end' => '02:00',
'desc' => 'Event description 200-2',
),
2 =>
array (
'start' => '00:00',
'end' => '01:00',
'desc' => 'Event description 210-1',
),
),
),
),
)
Upvotes: 0
Reputation: 7795
The following does what you're looking for:
$out = array();
foreach ($arr as $key => $value){
$cat = $value['cat'];
$dur = $value['dur'];
$type = $value['type'];
$out[$cat][$dur][$type][] = $value['start'].', '.$value['end'].', '.$value['desc'];
}
print_r($out);
EDIT:
I modified my code because of a request to use the last category when the category is empty. So, here's my modified code:
$out = array();
$last_cat = '';
foreach ($arr as $key => $value){
$cat = $value['cat'];
$dur = $value['dur'];
$type = $value['type'];
if (empty($cat)){
$cat = $last_cat;
} else {
$last_cat = $cat;
}
$out[$cat][$dur][$type][] = $value['start'].', '.$value['end'].', '.$value['desc'];
}
print_r($out);
The ouput of this code is as follows:
[FIRST CAT] => Array(
[10] => Array(
[Type description 10] => Array(
[0] => 00:00, 01:00, Event description 10-1
)
)
[] => Array(
[] => Array(
[0] => 01:00, 02:00, Event description 10-2
[1] => 02:00, 03:00, Event description 10-3
[2] => 01:00, 02:00, Event description 20-2
[3] => 01:00, 02:00, Event description 21-2
)
[Type description 21] => Array(
[0] => 00:00, 01:00, Event description 21-1
)
)
[20] => Array(
[Type description 20] => Array(
[0] => 00:00, 01:00, Event description 20-1
)
)
)
[SECOND CAT] => Array(
[10] => Array(
[Type description 100] => Array(
[0] => 00:00, 01:00, Event description 100-1
)
)
[] => Array(
[] => Array(
[0] => 01:00, 02:00, Event description 100-2
[1] => 01:00, 02:00, Event description 200-2
)
[Type description 210] => Array(
[0] => 00:00, 01:00, Event description 210-1
)
)
[20] => Array(
[Type description 200] => Array(
[0] => 00:00, 01:00, Event description 200-1
)
)
)
Upvotes: 1