Reputation: 19
I have the following result from a MySQL query with two joins.
Array (
[0] => Array ( [place_id] => 1 [place] => Berlin [lat] => 52.519 [lon] => 13.406 [id] => 1 [pname] => Firstschool [typ] => 0 [s_id] => 32 [fac] => history)
[1] => Array ( [place_id] => 1 [place] => Berlin [lat] => 52.519 [lon] => 13.406 [id] => 1 [pname] => Secondschool [typ] => 0 [s_id] => 33 [fac] => math)
[2] => Array ( [place_id] => 1 [place] => Berlin [lat] => 52.519 [lon] => 13.406 [id] => 1 [pname] => Secondschool [typ] => 0 [s_id] => 33 [fac] => english)
)
The data is redundant at some points, I need it this way:
Array (
[Berlin] => Array ( [lat] => 52.519
[lon] => 13.406
[schools] => Array([0]=> Firstschool [1]=>Secondschool)
)
[OtherCity] => Array ( ... )
)
First, is this okay or exists a better solution? =) Second.. how to split it for the needed result.
I tried it with something like the following code snippet, but it doesn't work as wished.
foreach($viewmodel as $item) {
$data[$item['place']][] = $item['pname'];
}
The result is:
Array ( [Berlin] => Array ( [0] => Firstschool [1] => Firstschool [2] => Firstschool ))
NOT so useful. ;)
I hope its understandable what I need. Maybe someone has an nice idea how to solve this problem.
Thanks for your time.
Upvotes: 0
Views: 1068
Reputation: 20753
I think you are on a right path, just need to fill in a little more detail:
$cities = Array (
Array ( 'place_id' => 1, 'place' => 'Berlin', 'lat' => 52.519, 'lon' => 13.406, 'id' => 1, 'pname' => 'Firstschool', 'typ' => 0, 's_id' => 32, 'fac' => 'history'),
Array ( 'place_id' => 1, 'place' => 'Berlin', 'lat' => 52.519, 'lon' => 13.406, 'id' => 1, 'pname' => 'Secondschool', 'typ' => 0, 's_id' => 33, 'fac' => 'math'),
Array ( 'place_id' => 1, 'place' => 'Berlin', 'lat' => 52.519, 'lon' => 13.406, 'id' => 1, 'pname' => 'Secondschool', 'typ' => 0, 's_id' => 33, 'fac' => 'english'),
);
// gather the transformed array in a new array
$out = array();
foreach ($cities as $city) {
// the first time we see the place
if (!isset($out[$city['place']])) {
// copy over what you want to keep
$out[$city['place']] = array(
'lat' => $city['lat'],
'lon' => $city['lon'],
'schools' => array($city['pname']),
);
} // only add $city['pname'] if we don't have it already
elseif (!in_array($city['pname'], $out[$city['place']]['schools'])) {
// we already seen this place, just add to the schools
$out[$city['place']]['schools'][] = $city['pname'];
}
}
For the gather faculties too question, use the school names as keys to arrays in the 'schools' key of the top level arrays, populate them like this: (still skipping duplicates):
foreach ($a as $city) {
if (!isset($out[$city['place']])) {
$out[$city['place']] = array(
'lat' => $city['lat'],
'lon' => $city['lon'],
'schools' => array($city['pname'] => array($city['fac'])),
);
} else {
// for convenience and readability, introducing some variables
$schools = &$out[$city['place']]['schools'];
$pname = $city['pname'];
$fac = $city['fac'];
// if we didn't see this school yet, add it with it's faculty
if (!isset($schools[$pname])) {
$schools[$pname] = array($fac);
} // if we did see this school before but the faculty is new, add it under the school's key
else if (!in_array($fac, $schools[$pname])) {
$schools[$pname][] = $fac;
}
}
}
Upvotes: 1
Reputation: 3094
The following should yield the described expected result
$arr = array(
array( 'place_id' => 1, 'place' => 'Berlin', 'lat' => 52.519, 'lon' => 13.406, 'id' => 1, 'pname' => 'Firstschool', 'typ' => 0, 's_id' => 32, 'fac' => 'history'),
array( 'place_id' => 1, 'place' => 'Berlin', 'lat' => 52.519, 'lon' => 13.406, 'id' => 1, 'pname' => 'Secondschool', 'typ' => 0, 's_id' => 32, 'fac' => 'history'),
array( 'place_id' => 1, 'place' => 'Berlin', 'lat' => 52.519, 'lon' => 13.406, 'id' => 1, 'pname' => 'Secondschool', 'typ' => 0, 's_id' => 32, 'fac' => 'history')
);
$result = array();
foreach($arr as $item) {
if (array_key_exists($item['place'], $result)) {
if (!in_array($item['pname'], $result[$item['place']]['schools'])) {
array_push($result[$item['place']]['schools'], $item['pname']);
}
} else {
$result[$item['place']]['lat'] = $item['lat'];
$result[$item['place']]['lon'] = $item['lon'];
$result[$item['place']]['schools'][] = $item['pname'];
}
}
print_r($result);
Which should output
Array (
[Berlin] => Array
(
[lat] => 52.519
[lon] => 13.406
[schools] => Array
(
[0] => Firstschool
[1] => Secondschool
)
)
)
Upvotes: 0
Reputation: 14620
You could map the array using a lambda function if you're using php 5.3+
$output = array();
$sort_schools = function($value, $key)
{
if ( ! is_array($output[$value['place'])
{
$output[$value['place'] = array();
}
if ( ! isset($output[$value['place']['lat'] && ! isset($output[$value['place']]['lon'])
{
$output[$value['place']]['lat'] = $value['lat'];
$output[$value['place']]['lon'] = $value['lon'];
}
$output[$value['place']]['schools'][] = $value['pname'];
};
array_map($sort_schools, $viewmodel);
Alternatively you could use a similar structure in the lambda function within a foreach loop or an anonymous function.
Upvotes: 0
Reputation: 2452
you are right, you have to iterate through the array some way or another. From the array I have seen, assuming all latitudes and longitudes are the same for all schools, overwriting will not hurt, otherwise, additional logic is needed
foreach($viewmodel as $item) {
$data[$item['place']['lat']=$item['lat'];
$data[$item['place']['long']=$item['lon'];
$data[$item['place']['schools'][]=$item['pname'];
}
Upvotes: 0