Reputation: 89
I've got the below $test
array sorted by 'date' and 'site'.
$test = array (
0 => array (
'id' => '45',
'rating' => 'p1',
'site' => 'Heavener SW',
'time' => '11-03-2012 Sat 10:00:00',
),
1 => array (
'id' => '45',
'rating' => 'h3',
'site' => 'Heavener SW',
'time' => '11-03-2012 Sat 10:00:00',
),
2 => array (
'id' => '45',
'rating' => 'h4',
'site' => 'Heavener SW',
'time' => '11-03-2012 Sat 16:00:00',
),
3 => array (
'id' => '110',
'rating' => 'p3',
'site' => 'Red Oak',
'time' => '11-03-2012 Sat 16:00:00',
),
4 => array (
'id' => '110',
'rating' => 'h3',
'site' => 'Red Oak',
'time' => '11-03-2012 Sat 16:00:00',
),
5 => array (
'id' => '32',
'rating' => 'p2',
'site' => 'Panopoint',
'time' => '11-04-2012 Sun 10:00:00',
)
);
I've gone nuts trying to combine 'ratings' for each 'site'-'time' combination.
$result = array (
0 => array (
'id' => '45',
'rating' => 'p1, h3',
'site' => 'Heavener SW',
'time' => '11-03-2012 Sat 10:00:00',
),
2 => array (
'id' => '45',
'rating' => 'h4',
'site' => 'Heavener SW',
'time' => '11-03-2012 Sat 16:00:00',
),
3 => array (
'id' => '110',
'rating' => 'p3, h3',
'site' => 'Red Oak',
'time' => '11-03-2012 Sat 16:00:00',
),
5 => array (
'id' => '32',
'rating' => 'p2',
'site' => 'Panopoint',
'time' => '11-04-2012 Sun 10:00:00',
)
);
There's no limits on the number of 'ratings' a site can have or how many 'sites' or 'time' there are (within reason).
Preserving the index in the $result
is optional (ie. not necessary).
I found this similar post(and others) but I don't understand how to implement. Getting all the related ones based on value
I've tried so many differnt ways my head is spinning, any help is greatly appreciated!
Upvotes: 3
Views: 74
Reputation: 270697
Since preserving the keys is optional, an easy option is to build a new array keyed by the unique pair site|time
while looping over the original.
For each of those, we'll also create an array of rating
values, and finally, implode()
that array into a string back to the 'ratings'
key.
$rekeyed = array();
foreach ($test as $item) {
// Build temporary key by concatenating site, time
$key = $item['site'] . '|' . $item['time'];
// If it already exists, add to the ratings
if (isset($rekeyed[$key])) {
$rekeyed[$key]['ratings'][] = $item['rating'];
}
else {
// Otherwise, set the key and the ratings array
$rekeyed[$key] = $item;
// And set the first rating, initialized as an array
$rekeyed[$key]['ratings'] = array();
$rekeyed[$key]['ratings'][] = $item['rating'];
}
}
// Finally, loop over and implode all the ratings back into a comma-separated string
foreach ($rekeyed as &$item) {
$item['rating'] = implode(',', $item['ratings']);
// Don't need the 'ratings' array anymore, unset it
unset($item['ratings']);
}
var_dump($rekeyed);
array(4) {
["Heavener SW|11-03-2012 Sat 10:00:00"]=>
array(5) {
["id"]=>
string(2) "45"
["rating"]=>
string(5) "p1,h3"
["site"]=>
string(11) "Heavener SW"
["time"]=>
string(23) "11-03-2012 Sat 10:00:00"
}
["Heavener SW|11-03-2012 Sat 16:00:00"]=>
array(5) {
["id"]=>
string(2) "45"
["rating"]=>
string(2) "h4"
["site"]=>
string(11) "Heavener SW"
["time"]=>
string(23) "11-03-2012 Sat 16:00:00"
}
["Red Oak|11-03-2012 Sat 16:00:00"]=>
array(5) {
["id"]=>
string(3) "110"
["rating"]=>
string(5) "p3,h3"
["site"]=>
string(7) "Red Oak"
["time"]=>
string(23) "11-03-2012 Sat 16:00:00"
}
["Panopoint|11-04-2012 Sun 10:00:00"]=>
&array(5) {
["id"]=>
string(2) "32"
["rating"]=>
string(2) "p2"
["site"]=>
string(9) "Panopoint"
["time"]=>
string(23) "11-04-2012 Sun 10:00:00"
}
}
Upvotes: 1
Reputation: 95141
You can simply use array_reduce
$test = array_reduce($test, function ($a, $b) {
isset($a[$b['time'] . "|" . $b['id']]) ? $a[$b['time'] . "|" . $b['id']]['rating'] .= "," . $b['rating'] : $a[$b['time'] . "|" . $b['id']] = $b;
return $a;
});
$test = array_values($test);
var_dump($test);
Output
array
0 =>
array
'id' => string '45' (length=2)
'rating' => string 'p1,h3' (length=5)
'site' => string 'Heavener SW' (length=11)
'time' => string '11-03-2012 Sat 10:00:00' (length=23)
1 =>
array
'id' => string '45' (length=2)
'rating' => string 'h4' (length=2)
'site' => string 'Heavener SW' (length=11)
'time' => string '11-03-2012 Sat 16:00:00' (length=23)
2 =>
array
'id' => string '110' (length=3)
'rating' => string 'p3,h3' (length=5)
'site' => string 'Red Oak' (length=7)
'time' => string '11-03-2012 Sat 16:00:00' (length=23)
3 =>
array
'id' => string '32' (length=2)
'rating' => string 'p2' (length=2)
'site' => string 'Panopoint' (length=9)
'time' => string '11-04-2012 Sun 10:00:00' (length=23)
Upvotes: 2
Reputation: 3787
I think PHP foreach loops go in order, so this should work. I haven't tested it, so let me know how it goes.
$previous_id = '';
// for each row, check if it was the same as the previous row (since you have sorted it properly)
foreach($result as $k => $row){
// if it matches the previous, add the rating and remove now duplicate row
if ($row['time'] == $result[$previous_id]['time']
&& $row['site'] == $result[$previous_id]['site']){
$result[$previous_id]['rating'] .= ', '.$row['rating'];
unset($result[$k]);
} // otherwise, set new previous_id to check
else {
$previous_id = $k;
}
}
This has the added benefit of keeping the first row-id that you come across, but may not be particularly optimized.
Upvotes: 0