Get selected columns from a multidimensional array using an array of DOT name keys

I have the following array

 $ users = Array ([0] => Array ([id] => 16 [name] => Dr. Arti Luthra [email] => artiluthra@dsingh.com [gender] => female [mobile] => 123456789 [status ] => 0 [addresses] => Array ([0] => Array ([id] => 16 [clinic_name] => Luthra Medical Center [address] => A-65/2, Meera Bhagh [contact_no] => 2342345234 [formatted_address] => A-65/2, Meera Bhagh Rohini, West Delhi, Delhi [timings] => Array ([0] => Array ([start] => 09:00 AM [end] => 02: 00 PM) [1] => Array ([start] => 05:00 PM [end] => 08:00 PM))) [1] => Array ([id] => 17 [clinic_name] => Luthra Medical Center [address] => A-65/2, Chanakyapuri [contact_no] => 123456789 [formatted_address] => A-65/2, Chanakyapuri Chanakyapuri, South Delhi, Delhi [timings] => Array ([0] => Array ([start] => 09:00 AM [end] => 02:00 PM))))) [1] => Array ([id] => 39 [name] => Sudhir Seth [email] => sudhirseth@gmail.com [gender] => male [mobile] => 65565656565 [status] => 0 [addresses] => Array ([0] => Array ([id] => 54 [clinic_name] => Dr. Sudhir  Seth Orthopoint [address] => D-595, Chittranjan Park, Landmark: Besides Deshbandhu College, Delhi [contact_no] => [formatted_address] => D-595, Chittranjan Park, Landmark: Besides Deshbandhu College, Delhi Greater Kailash, South Delhi , Delhi [timings] => Array ([0] => Array ([start] => 10:30 AM [end] => 01:00 PM) [1] => Array ([start] => 06:00 PM [end] => 09:00 PM))) [1] => Array ([id] => 55 [clinic_name] => Fortis C-Doc [address] => B-16, Chirag Enclave, Nehru Place.  Landmark: Opp.  to Nehru Place, Delhi [contact_no] => [formatted_address] => B-16, Chirag Enclave, Nehru Place.  Landmark: Opp.  to Nehru Place, Delhi Lajpat Nagar, South Delhi, Delhi [timings] => Array ([0] => Array ([start] => 09:00 AM [end] => 11:00 AM)))))) 

I want to get the selected keys using dot notation like

getKeys ($ users, array ('name', 'email', 'addresses.address', 'addresses.clinic_name', 'addresses.timings.start'))

Using the getKeys () method above, the result should be:

  Array
 (
     [0] => Array
         (
             [name] => Dr.  Arti luthra
             [email] => artiluthra@dsingh.com
             [addresses] => Array
                 (
                     [0] => Array
                         (
                             [clinic_name] => Luthra Medical Center
                             [address] => A-65/2, Meera Bhagh
                             [timings] => Array
                                 (
                                     [0] => Array
                                         (
                                             [start] => 09:00 AM
                                         )

                                     [1] => Array
                                         (
                                             [start] => 05:00 PM
                                         )

                                 )

                         )

                     [1] => Array
                         (
                             [clinic_name] => Luthra Medical Center
                             [address] => A-65/2, Chanakyapuri
                             [timings] => Array
                                 (
                                     [0] => Array
                                         (
                                             [start] => 09:00 AM
                                         )

                                 )

                         )

                 )

         )

     [1] => Array
         (
             [name] => Sudhir Seth
             [email] => sudhirseth@gmail.com
             [addresses] => Array
                 (
                     [0] => Array
                         (
                             [clinic_name] => Dr.  Sudhir Seth Orthopoint
                             [address] => D-595, Chittranjan Park, Landmark: Besides Deshbandhu College, Delhi
                             [timings] => Array
                                 (
                                     [0] => Array
                                         (
                                             [start] => 10:30 AM
                                         )

                                     [1] => Array
                                         (
                                             [start] => 06:00 PM
                                         )

                                 )

                         )

                     [1] => Array
                         (
                             [clinic_name] => Fortis C-Doc
                             [address] => B-16, Chirag Enclave, Nehru Place.  Landmark: Opp.  to Nehru Place, Delhi
                             [timings] => Array
                                 (
                                     [0] => Array
                                         (
                                             [start] => 09:00 AM
                                         )

                                 )

                         )

                 )

         )

 )

+5
source share
3 answers

This question seems to be very close to xPath for xml structures.

It is also interesting that jsonPath for json for example:

JsonPath in PHP - https://github.com/Skyscanner/JsonPath-PHP

JsonPath in Myqsl - https://dev.mysql.com/doc/refman/5.7/en/json-path-syntax.html

But, unfortunately, for php-array this technology has not yet been implemented.

Good time to write your own library (phpPath)!

As for your particular slightly different case:

/** * Search values by phpPath * * @param array $aData * @param string|array $phpPath * @param array &$aReturn * @return array */ function getKeys($aData, $phpPath = [], &$aReturn = []) { //Support arrays of $phpPath if (is_array($phpPath)) { foreach ($phpPath as $path) { getKeys($aData, $path, $aReturn); } return $aReturn; } //Get next sought-for key $aParts = explode('.', $phpPath); $sNeedle = array_shift($aParts); $sRemain = implode('.', $aParts); foreach ($aData as $k => $v) { //skip numeric keys //@todo need to thinking about //needs to add * (wildcard) into phpPath for that purpose if (is_numeric($k) && $phpPath) { getKeys($v, $phpPath, $aReturn[$k]); continue; } //Is it key that we want if ($k !== $sNeedle) { continue; } //Checking needs deeper search if (is_array($v) && $sRemain) { getKeys($v, $sRemain, $aReturn[$k]); continue; } //Need to save fully-qualified found value $aReturn[$k] = $v; break; } return $aReturn; } 

Usage example:

 var_dump( getKeys($users, array( 'name', 'email', 'addresses.address', 'addresses.clinic_name', 'addresses.timings.start' )) ); 
+3
source

This solution will work. It calls the class that will create the string, and then the json_decode string to create the array you are looking for. Two files were created, one of which contains a class, and the other an instance of an object from this class.

ArrayManager.php defines the class

 class ArrayManager{ var $out = ''; function __construct($in, $params){ $this->params = $params; $this->getKeys($in, $params); $this->out = json_decode($this->out, TRUE); } function getKeys($in, $params){ $this->out = '['; $this->traverseArray($in); $this->out .= ']'; } function traverseArray($in, $keyString='', $lastKey=''){ if(!is_array($in)){ if(in_array(substr($keyString, 1), $this->params)){ $this->out .= '"'.$in.'",'; }else{ $this->out = rtrim($this->out, '"'.$lastKey.'":'); } return; } $this->out .= '{'; foreach($in as $key=>$value){ $this->out .= '"'.$key.'":'; if(is_numeric($key)){ $result = $this->traverseArray($value, $keyString, $key); $this->out .= ','; }else{ $result = $this->traverseArray($value, $keyString.'.'.$key, $key); } } $this->out = rtrim($this->out, ','); $this->out .= '}'; } } 

runArrayManager.php just contains your array of samples and code to call the ArrayManager class.

 require_once('ArrayManager.php'); $params = array('name','email','addresses.address','addresses.clinic_name','addresses.timings.start'); $users = *your sample array* $obj = new ArrayManager($users, $params); $newArray = $obj->out; 
0
source

This function should handle one path separated by a period:

 function map_path($path,$arr) { if (($path=='')||(isEmpty($arr))) return array(); $start=strpos($path,'.'); if ($start>=0) { $prefix=substr($path,0,$start); $suffix=substr($path,$start+1); return array_map(function ($a) {return array( $prefix => map_path($suffix,$a)) );},$arr); } else return array($path => $array[$path]); } 

To support multiple paths, just iterate:

 $paths=array('name','email','addresses.address','addresses.clinic_name','addresses.timings.start'); $res=array(); for ($paths as $path) $res[$path]=map_path($path,$arr); 
0
source

All Articles