0

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.

4 Answers 4

1

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

6 Comments

Wow, thanks. This works. But I have a little question, though. Now in this way, he give me the school for every result, even if this school is already mentioned. In this case, I get secondschool two times. I thought I can stop this with if (!isset($out[$city['place']]['schools'])) , but then, I only get the firstschool and nothing more. =)
Oh, i didn't realized that, updated the answer. Actually, there's a lot of different way to go about that, added a pretty straightforward one.
Yeah thanks. Your answer works perfect, too. =) Thanks for all you help. Just as a bonus question, is it possible to add the different lesson types (math, history.. not every school has the same) to the school as a sub array again, so tree dimensions? Or is this a bad idea in terms of working with this array? =)
Well, you could certainly make it work adding arrays to the schools key, using the $city['pname'] and an array under that key that would hold the $city['fac'] as the values. But at this point its getting a little hairy for primitives i think (-:
@user2081104, I've added an implementation.
|
0

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

Comments

0

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.

Comments

0

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
             )

     )
)

1 Comment

Ha, this works like a charm it seems. I'll test it a little bit and stuff and mark it later a solution for my Problem. Thanks dude.

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.