Splitting a MySQL Query result into an multidimensional-array - php

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.

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

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

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.

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
)
)
)

Related

How to merge two array if one item exist in both array?

I want to expand my city array with post code value.
If the city_postcode array contain city array name record then push postcode value into city array. That's what i want to achive somehow.
city array:
Array
(
[0] => Array
(
[id] => 1
[city] => Budapest
[population] => 1700000
)
[1] => Array
(
[id] => 2
[city] => Szeged
[population] => 160000
)
)
city_postcode array:
Array
(
[0] => Array
(
[name] => Budapest
[post_code] => 12345
)
[1] => Array
(
[name] => Szeged
[post_code] => 33356
)
)
The result I want:
Array
(
[0] => Array
(
[id] => 1
[city] => Budapest
[population] => 1700000
[post_code] => 12345
)
[1] => Array
(
[id] => 2
[city] => Szeged
[population] => 160000
[post_code] => 33356
)
)
If you can rely on the cities and post codes to be equal in length and sorted, you could just do something like this:
<?php
$cities = array(
array("id"=>1,"city"=>"Budapest","Population"=>"1700000"),
array("id"=>2,"city"=>"Szeged","Population"=>"160000")
);
$cityPostCode = array(
array("name"=>"Budapest","post_code"=>12345),
array("name"=>"Szeged","post_code"=>33356)
);
for($i = 0; $i < count($cities); $i++){
$cities[$i]['post_code'] = $cityPostCode[$i]['post_code'];
}
print_r($cities);
Other wise you could do something more dyanmic like:
function _parsePostCode($targetName,$targetArr){
foreach($targetArr as $el){
if($el['name'] == $targetName){
return $el['post_code'];
}
}
return false;
}
for($i = 0; $i < count($cities); $i++){
$cities[$i]['post_code'] = _parsePostCode($cities[$i]['city'],$cityPostCode);
}
print_r($cities);
As an alternative you can use 'reference' PHP in foreach loop as follows
$city = array(
0 => array(
'id' => 1,
'city' => "Budapest",
'population' => 1700000
),
1 => array(
'id' => 2,
'city' => "Szeged",
'population' => 160000
)
);
$city_postcode = array(
0 =>array(
'name' => 'Budapest',
'post_code' => 12345
),
1 => array(
'name' => 'Szeged',
'post_code' => 33356
)
);
foreach ($city as $ckey => &$cval) {
$cval['post_code'] = $city_postcode[$ckey]['post_code'];
}
unset($cval);
var_dump($city);
You can use this simple approach :
<?php
$city = array(
0 => array(
'id' => 1,
'city' => "Budapest",
'population' => 1700000
),
1 => array(
'id' => 2,
'city' => "Szeged",
'population' => 160000
)
);
$city_postcode = array(
0 => array(
'name' => 'Budapest',
'post_code' => 12345
),
1 => array(
'name' => 'Szeged',
'post_code' => 33356
)
);
function apply_post_code(&$item, $key, $postcode)
{
$item['post_code'] = $postcode[ $key ][ 'post_code' ];
}
array_walk($city, 'apply_post_code', $city_postcode);
var_dump($city);
Note that the $city variable has been passes by reference

Remove some keys from an array inside another array in PHP (Laravel)

How to remove some keys from an array inside another array in PHP?
I have this structure:
array (
0 =>
array (
'num' => '123',
'nome' => 'test 001'
'pontos' => 68,
'data_status' => '03/09/2021 10:05',
'uuid_status' => '69450ea451ae11ea85ca309c23d3a0ed'
),
1 =>
array (
'num' => '345',
'nome' => 'test 002'
'pontos' => 120,
'data_status' => '27/08/2021 15:46',
'uuid_status' => '3cbf4fd15d5411ea86956eef5d66cb13',
),
)
and need to return something like this:
array (
0 =>
array (
'num' => '123',
'nome' => 'test 001'
'pontos' => 68
),
1 =>
array (
'num' => '345',
'nome' => 'test 002'
'pontos' => 120
)
)
I've seen some answers but they seem to be outdated, also i'm using Laravel, so it would help if someone point me out something from the framework and its equivalent in pure PHP
A simple foreach loop is a good starting point, note this will remove items from the original array, by using the reference & to the array rather than a normal simple copy. On the $val in the foreach ( $input as &$val){
$input = [
[
'num' => '123',
'nome' => 'test 001',
'pontos' => 68,
'data_status' => '03/09/2021 10:05',
'uuid_status' => '69450ea451ae11ea85ca309c23d3a0ed'
],[
'num' => '345',
'nome' => 'test 002',
'pontos' => 120,
'data_status' => '27/08/2021 15:46',
'uuid_status' => '3cbf4fd15d5411ea86956eef5d66cb13'
]
];
$remove = ['data_status','uuid_status'];
foreach ( $input as &$val){
foreach ($val as $k => $v) {
if ( in_array($k,$remove) ) {
unset( $val[$k]);
}
}
}
print_r($input);
RESULT
Array
(
[0] => Array
(
[num] => 123
[nome] => test 001
[pontos] => 68
)
[1] => Array
(
[num] => 345
[nome] => test 002
[pontos] => 120
)
)
Probably not the most concise, but it gets the job done:
$bad_keys = array('data_status', 'uuid_status');
$array = array (
0 =>
array (
'num' => '123',
'nome' => 'test 001',
'pontos' => 68,
'data_status' => '03/09/2021 10:05',
'uuid_status' => '69450ea451ae11ea85ca309c23d3a0ed',
),
1 =>
array (
'num' => '345',
'nome' => 'test 002',
'pontos' => 120,
'data_status' => '27/08/2021 15:46',
'uuid_status' => '3cbf4fd15d5411ea86956eef5d66cb13',
),
);
function traverse_array($array, $bad_keys) {
foreach ($array as $key => $value) {
if (is_array($value)) {
$array[$key] = traverse_array($value, $bad_keys);
} else {
foreach ($bad_keys as $remove_me) {
if ($key == $remove_me) {
unset($array[$key]);
}
}
}
}
return $array;
}
print_r(traverse_array($array, $bad_keys));

PHP - Merge 2 multidimensional array based on value

Currently, I have 2 multidimensional array and I'm looking to combine them into one giant array where the value's name in array 1 matches the value's name in array 2.
The array's look as followed...
Array1
(
[0] => Array
(
[id] => 1
[name] => test1
[desc] => test_desc
[quantity] => 3
)
[1] => Array
(
[id] => 2
[name] => test2
[desc] => test_desc
[quantity] => 33
)
)
Array2
(
[0] => Array
(
[holder] => 'John'
[name] => test1
[desc] => test_desc
[location] => ATL
)
[1] => Array
(
[holder] => 'Jackie'
[name] => test3
[desc] => test_desc
[location] => SF
)
)
I'm looking to merge the arrays where the 'name' column in array1 matches in array2 and also combine the columns in array's 1 & 2 into the final array. This should look like...
FinalArray
(
[0] => Array
(
[id] => 1
[holder] => 'John'
[name] => test1
[desc] => test_desc
[location] => ATL
[quantity] => 3
)
[1] => Array
(
[holder] => 'Jackie'
[name] => test3
[desc] => test_desc
[location] => SF
)
[2] => Array
(
[id] => 2
[name] => test2
[desc] => test_desc
[quantity] => 33
)
)
Where the "test1" combines the different columns across the 2 arrays into a new array inside the "FinalArray". I've tried researching some ideas with array_merge and array_merge_recursive but I'm not entirely sure if I'm going in the correct direction. Thanks in advance.
Try like this
$array1=[['id' => 1,'name' => 'test1','desc' => 'test_desc','quantity' => 3],
['id' => 2,'name' => 'test2','desc' => 'test_desc','quantity' => 33]];
$array2=[['holder' => 'John','name' => 'test1','desc' => 'test_desc','location' => 'ATL'],
['holder' => 'Jackie','name' => 'test3','desc' => 'test_desc','location' => 'SF']];
$final=[];
foreach ($array1 as $key1=>$data1){
foreach ($array2 as $key2=>$data2){
if($data1['name']==$data2['name']){
$final[]=$data1+$data2;
unset($array1[$key1]);
unset($array2[$key2]);
}
}
}
if(!empty($array1)){
foreach ($array1 as $value){
$final[]=$value;
}
}
if(!empty($array2)){
foreach ($array2 as $value){
$final[]=$value;
}
}
It will give output as
One more solution
function merge_by_name(array $arr1, array $arr2) {
$result = [];
foreach ($arr1 as $value) {
$key = array_search($value['name'], array_column($arr2, 'name'));
if($key !== false) {
$result[] = array_merge($value, $arr2[$key]);
unset($arr2[$key]);
} else {
$result[] = $value;
}
}
$result = array_merge($result, $arr2);
return $result;
}
Test
$arr1 = [
[
'id' => 1,
'name' => 'test1',
'desc' => 'test_desc',
'quantity' => 3
],
[
'id' => 2,
'name' => 'test2',
'desc' => 'test_desc',
'quantity' => 33
],
];
$arr2 = [
[
'holder' => 'John',
'name' => 'test1',
'desc' => 'test_desc',
'location' => 'ATL'
],
[
'holder' => 'Jackie',
'name' => 'test3',
'desc' => 'test_desc',
'location' => 'SF'
],
];
var_export(merge_by_name($arr1, $arr2));
Result
array (
0 =>
array (
'id' => 1,
'name' => 'test1',
'desc' => 'test_desc',
'quantity' => 3,
'holder' => 'John',
'location' => 'ATL',
),
1 =>
array (
'id' => 2,
'name' => 'test2',
'desc' => 'test_desc',
'quantity' => 33,
),
2 =>
array (
'holder' => 'Jackie',
'name' => 'test3',
'desc' => 'test_desc',
'location' => 'SF',
),
)

Php sort array on based of another array and one sub array field

I am trying to create an application which find near by restaurants, I have used a database to retrieve near by zipcodes
so I now have an array like
$sortLike=array(60007,60001,60003,60002);
and database return array like
$array1= array( array ('ID' => 138,'zip_code' => 60007,'approved' => 1),
array('ID' => 103,'zip_code' => 60007,'approved' => 0),
array('ID' => 124,'zip_code' => 60002,'approved' => 0),
array('ID' => 104,'zip_code' => 60002,'approved' => 1),
array('ID' => 105,'zip_code' => 60003,'approved' => 0),
array('ID' => 106,'zip_code' => 60001,'approved' => 0),
array('ID' => 114,'zip_code' => 60007,'approved' => 0)
);
So I need to show all restaurants that are approved but in order of $sortLike array
i.e returned array should be
$array1= array(
array ('ID' => 138,'zip_code' => 60007,'approved' => 1),
array('ID' => 103,'zip_code' => 60007,'approved' => 0),
array('ID' => 114,'zip_code' => 60007,'approved' => 0)
array('ID' => 106,'zip_code' => 60001,'approved' => 0),
array('ID' => 105,'zip_code' => 60003,'approved' => 0),
array('ID' => 104,'zip_code' => 60002,'approved' => 1),
array('ID' => 124,'zip_code' => 60002,'approved' => 0),
);
Here is what I tried
function sortarray1($mylist,$mainZipSearch){
$newList=$newList2=$newList3 = array();
$j=$k=$l=0;
if(count($mylist))
{
foreach($mylist as $k=>$v) {
if( $v['approved']==1 && $v['zip_code']==$mainZipSearch){
$newList[$j] = $mylist[$k];
}
else if( $v['approved']==0 && $v['zip_code']==$mainZipSearch){
$newList2[$k] = $mylist[$k];
}
else{
$newList3[$l] = $mylist[$k];
}
$j++;$k++;$l++;
}
$newList=array_values($newList);
$newList2=array_values($newList2);
$newList3=array_values($newList3);
$arr=array_merge($newList,$newList2,$newList3 );
}
return
}
You're going way too far !
Using usort makes such problems easier to handle.
function sort_results ($a, $b) {
$sortLike=array(60007,60001,60003,60002);
// Push unknown values at the end of the array
if (!in_array ($a['zip_code'], $sortLike)) { return 1; }
return array_search($a['zip_code'], $sortLike) > array_search($b['zip_code'], $sortLike);
}
usort ($arr, 'sort_results');
print_r ($arr);
Array (
[0] => Array ( [ID] => 114 [zip_code] => 60007 [approved] => 0 )
[1] => Array ( [ID] => 103 [zip_code] => 60007 [approved] => 0 )
[2] => Array ( [ID] => 138 [zip_code] => 60007 [approved] => 1 )
[3] => Array ( [ID] => 106 [zip_code] => 60001 [approved] => 0 )
[4] => Array ( [ID] => 105 [zip_code] => 60003 [approved] => 0 )
[5] => Array ( [ID] => 124 [zip_code] => 60002 [approved] => 0 )
[6] => Array ( [ID] => 104 [zip_code] => 60002 [approved] => 1 )
[7] => Array ( [ID] => 184 [zip_code] => 60022 [approved] => 0 )
)
This is why we have relational databases. If you have a query which returns the sorted list of Zipcodes, then simply join the query which returns the approved restaurants.
You could try something like this:
<?
$sortLike=array(60007,60001,60003,60002);
$array1= array( array ('ID' => 138,'zip_code' => 60007,'approved' => 1),
array('ID' => 103,'zip_code' => 60007,'approved' => 0),
array('ID' => 124,'zip_code' => 60002,'approved' => 0),
array('ID' => 104,'zip_code' => 60002,'approved' => 1),
array('ID' => 105,'zip_code' => 60003,'approved' => 0),
array('ID' => 106,'zip_code' => 60001,'approved' => 0),
array('ID' => 114,'zip_code' => 60007,'approved' => 0)
);
function removeNonApproved($var) {
return $var['approved'];
}
function cmp($a,$b) {
global $sortLike;
return (array_search($a['zip_code'],$sortLike) < array_search($b['zip_code'],$sortLike) ) ? -1 : 1;
}
// Remove non approved items
$array1 = array_filter($array1,"removeNonApproved");
// Sort your array
usort($array1, "cmp");
var_dump($array1);
?>

PHP associative multidimentional array - print only selected keys

I have an array that is taken from an image using
exif_read_data($image, 0, true)
The array itself can contain an unknown number of keys/values (can also be 0)
The array is also Multidimentional in some parts.
An example of an array from exif_read_data :
Array
(
[FILE] => Array
(
[FileName] => f-20110129_004_pp.jpg
[FileDateTime] => 0
[FileSize] => 3566966
[FileType] => 2
[MimeType] => image/jpeg
[SectionsFound] => ANY_TAG, IFD0, THUMBNAIL, EXIF, GPS
)
[COMPUTED] => Array
(
[html] => width="2576" height="1936"
[Height] => 1936
[Width] => 2576
[IsColor] => 1
[ByteOrderMotorola] => 0
[ApertureFNumber] => f/2.8
[Thumbnail.FileType] => 2
[Thumbnail.MimeType] => image/jpeg
)
[IFD0] => Array
(
[ImageWidth] => 2576
[ImageLength] => 1936
[BitsPerSample] => Array
(
[0] => 8
[1] => 8
[2] => 8
)
[Make] => Nokia
[Model] => N900
[Orientation] => 1
[SamplesPerPixel] => 3
[XResolution] => 3000000/10000
[YResolution] => 3000000/10000
[ResolutionUnit] => 2
[Software] => Adobe Photoshop CS5 Windows
[DateTime] => 2011:01:29 09:37:30
[YCbCrPositioning] => 1
[Exif_IFD_Pointer] => 276
[GPS_IFD_Pointer] => 658
)
[THUMBNAIL] => Array
(
[Compression] => 6
[XResolution] => 72/1
[YResolution] => 72/1
[ResolutionUnit] => 2
[JPEGInterchangeFormat] => 978
[JPEGInterchangeFormatLength] => 5525
)
[EXIF] => Array
(
[ExposureTime] => 1/500
[FNumber] => 14/5
[ExposureProgram] => 0
[ISOSpeedRatings] => 100
[ExifVersion] => 0210
[DateTimeOriginal] => 2011:01:29 09:37:30
[DateTimeDigitized] => 2011:01:29 09:37:30
[ShutterSpeedValue] => 8/1
[ApertureValue] => 297/100
[LightSource] => 0
[Flash] => 0
[FocalLength] => 26/5
[FlashPixVersion] => 0100
[ColorSpace] => 1
[ExifImageWidth] => 2576
[ExifImageLength] => 1936
[CustomRendered] => 0
[ExposureMode] => 0
[WhiteBalance] => 0
[DigitalZoomRatio] => 1/1
[SceneCaptureType] => 0
[GainControl] => 0
[Contrast] => 0
[Saturation] => 0
)
[GPS] => Array
(
[GPSVersion] =>
[GPSLatitudeRef] => N
[GPSLatitude] => Array
(
[0] => 22/1
[1] => 12937/1000
[2] => 0/1
)
[GPSLongitudeRef] => E
[GPSLongitude] => Array
(
[0] => 113/1
[1] => 32886/1000
[2] => 0/1
)
[GPSAltitudeRef] =>
[GPSAltitude] => 255/1
[GPSTimeStamp] => Array
(
[0] => 9/1
[1] => 37/1
[2] => 30/1
)
[GPSMapDatum] => WGS-84
[GPSDateStamp] => 2011:01:29
)
)
My question is how can I create a function that will display only the keys that I select , as a key/value pair , even if it is in the 2nd, or 3rd dimension of the array?
for example - from the array above , if I want to select only the [ImageWidth] , [ImageLength] , [XResolution] , [GPSTimeStamp] and [GPSLatitude] ..
I would pass it to the function like :
$keys_array = (ImageWidth , ImageLength, XResolution, GPSTimeStamp , GPSLatitude)
and then
function select_keys_from_array ($keys_array='') {
// if $keys_array=='' then get all ..
//identify the dimension or flatten - and get only my keys and display key/value
}
I have selected those keys as example because some of them are on a second-level, and some are actually arrays themselves ..
There is also a problem is that the keys can theoretically be duplicated (user-keys) - but residing in different second-level array (and therefor not nominally duplicated.)
I guess I will need to "flatten" it first , and then to "pass" an array of my wanted keys somehow - but I can not really seem to get it right .
Does someone knows any ready-made class / function / snippet for that sort of thing ?
(Disclaimer; may do wacky stuff, not fully tested -- should be fine though)
Last edit; the first one was better, as it didn't exclude array values (such as coordinates, etc.)
function array_by_keys_recursive(array $keys, array $array) {
$results = array();
foreach ($keys as $key) {
if (isset($array[$key])) {
$results[$key] = $array[$key];
continue;
}
foreach ($array as $value) {
if (\is_array($value)) {
$results = \array_replace($results,
\array_by_keys_recursive(array($search), $value));
}
}
}
return $results;
}
Test:
$array = array(
'a' => 1,
'b' => 2,
'c' => array(
'd' => 3,
'e' => 4,
),
'f' => 5,
'g' => array(
'h' => array(
'i' => 6,
'j' => 7,
),
'k' => 8,
),
);
\var_dump(\array_by_keys_recursive(array('a', 'b', 'c', 'h', 'i', 'j'), $array));
Results:
array(6) {
["a"]=>
int(1)
["b"]=>
int(2)
["c"]=>
array(2) {
["d"]=>
int(3)
["e"]=>
int(4)
}
["h"]=>
array(2) {
["i"]=>
int(6)
["j"]=>
int(7)
}
["i"]=>
int(6)
["j"]=>
int(7)
}
You don't necessarily need to flatten it - in fact, doing so may overwrite those keys you mentioned that might appear in more than one sub-array. You just need to be able to successfully walk the array, including nested arrays, using recursion (the routine would read a single array from start to finish, but would call itself recursively for every sub-array it encounters). Once you can walk it like this, then you can simply compare the keys you are encountering against the ones you want.
If you want specific versions of keys that appear in multiple places then you are going to have to qualify them ('scope' them) somehow - for example, using COMPUTED.Height rather than just Height. Your walking algorithm will have to keep track of the path through the array (i.e., the parent array chain it has walked to get that far) to allow this comparison.
Write a recursive function that converts a multidimensional array to a flat one and eliminate duplicate keys, or those you don't want.
function multi2flat($array)
{
$return = array();
array_walk_recursive($array, function($a) use (&$return) { $return[] = $a; });
return $return;
}
<?
$x = Array
(
'FILE' => Array
(
'FileName' => 'f-20110129_004_pp.jpg',
'FileDateTime' => 0,
'FileSize' => 3566966,
'FileType' => 2,
'MimeType' => 'image/jpeg',
'SectionsFound' => 'ANY_TAG, IFD0, THUMBNAIL, EXIF, GPS',
),
'COMPUTED' => Array
(
'html' => 'width="2576" height="1936"',
'Height' => 1936,
'Width' => 2576,
'IsColor' => 1,
'ByteOrderMotorola' => 0,
'ApertureFNumber' => 'f/2.8',
'Thumbnail.FileType' => 2,
'Thumbnail.MimeType' => 'image/jpeg',
),
'IFD0' => Array
(
'ImageWidth' => 2576,
'ImageLength' => 1936,
'BitsPerSample' => Array
(
'0' => 8,
'1' => 8,
'2' => 8,
),
'Make' => 'Nokia',
'Model' => 'N900',
'Orientation' => 1,
'SamplesPerPixel' => 3,
'XResolution' => '3000000/10000',
'YResolution' => '3000000/10000',
'ResolutionUnit' => 2,
'Software' => 'Adobe Photoshop CS5 Windows',
'DateTime' => '2011:01:29 09:37:30',
'YCbCrPositioning' => 1,
'Exif_IFD_Pointer' => 276,
'GPS_IFD_Pointer' => 658,
),
'THUMBNAIL' => Array
(
'Compression' => 6,
'XResolution' => '72/1',
'YResolution' => '72/1',
'ResolutionUnit' => 2,
'JPEGInterchangeFormat' => 978,
'JPEGInterchangeFormatLength' => 5525,
),
'EXIF' => Array
(
'ExposureTime' => '1/500',
'FNumber' => '14/5',
'ExposureProgram' => 0,
'ISOSpeedRatings' => 100,
'ExifVersion' => '0210',
'DateTimeOriginal' => '2011:01:29 09:37:30',
'DateTimeDigitized' => '2011:01:29 09:37:30',
'ShutterSpeedValue' => '8/1',
'ApertureValue' => '297/100',
'LightSource' => 0,
'Flash' => 0,
'FocalLength' => '26/5',
'FlashPixVersion' => '0100',
'ColorSpace' => 1,
'ExifImageWidth' => 2576,
'ExifImageLength' => 1936,
'CustomRendered' => 0,
'ExposureMode' => 0,
'WhiteBalance' => 0,
'DigitalZoomRatio' => '1/1',
'SceneCaptureType' => 0,
'GainControl' => 0,
'Contrast' => 0,
'Saturation' => 0,
),
'GPS' => Array
(
'GPSVersion' => '',
'GPSLatitudeRef' => 'N',
'GPSLatitude' => Array
(
'0' => '22/1',
'1' => '12937/1000',
'2' => '0/1',
),
'GPSLongitudeRef' => 'E',
'GPSLongitude' => Array
(
'0' => '113/1',
'1' => '32886/1000',
'2' => '0/1',
),
'GPSAltitudeRef' => '',
'GPSAltitude' => '255/1',
'GPSTimeStamp' => Array
(
'0' => '9/1',
'1' => '37/1',
'2' => '30/1',
),
'GPSMapDatum' => 'WGS-84',
'GPSDateStamp' => '2011:01:29',
),
);
function get_values( $data, $keys ) {
$ret = Array();
foreach( $data as $k => $v ) {
if( is_array( $v ) ) {
$t = get_values( $v, $keys );
if( is_array( $t ) && sizeOf( $t ) > 0 ) {
$ret[$k] = $t;
}
} else {
if( in_array( $k, $keys ) ) {
$ret[ $k ] = $v;
}
}
}
return $ret;
}
print_r( get_values( $x, Array( 'ImageWidth', 'ImageLength', 'XResolution', 'GPSLatitude' ) ) );
?>

Categories