使用DOT符号键数组从多维数组中获取选定列



我有以下数组

$users=阵列([0]=>数组([id]=>16[name]=>Arti Luthra博士[电子邮件]=>artiluthra@dsingh.com[gender]=>女性[移动电话]=>123456789[状态]=>0[地址]=>阵列([0]=>数组([id]=>16[临床名称]=>卢特拉医疗中心[地址]=>A-65/2,Meera Bhagh[contact_no]=>2342345234[formated_address]=>A-65/2,Meera Bhagh Rohini,西德里,德里[timings]=>阵列([0]=>数组([start]=>上午09:00[end]=>02:00 PM)[1] =>阵列([start]=>05:00 PM[end]=>08:00 PM)))[1] =>阵列([id]=>17[临床名称]=>卢特拉医疗中心[地址]=>A-65/2,Chanakyapuri[contact_no]=>123456789[formated_address]=>A-65/2,Chanakyapuri,South Delhi,Delhi[timings]=>阵列([0]=>数组([start]=>上午09:00[end]=>02:00 PM)))))[1] =>阵列([id]=>39[name]=>Sudhir Seth[电子邮件]=>sudhirseth@gmail.com[gender]=>男性[手机]=>65565656565[状态]=>0[地址]=>阵列([0]=>数组([id]=>54[clinical_name]=>Sudhir Seth医生骨科[地址]=>D-595,Chittranjan公园,地标:除德里Deshbandhu学院外[contact_no]=>[formated_address]=>D-595,Chitranjan公园,地标:除Deshbandhu学院外,德里大凯拉什,德里南部[timings]=>阵列([0]=>数组([start]=>上午10:30[end]=>01:00 PM)[1] =>阵列([start]=>06:00 PM[end]=>09:00 PM)))[1] =>阵列([id]=>55[临床名称]=>Fortis C-Doc[地址]=>B-16,Chirag Enclave,Nehru Place。地标:Opp.to Nehru Place,德里[contact_no]=>[formated_address]=>B-16,Chirag Enclave,Nehru Place。地标:Opp.to Nehru Place,德里Lajpat Nagar,南德里,德里[timings]=>阵列([0]=>数组([start]=>上午09:00[end]=>上午11:00))))))

我想使用像这样的点符号来获得选定的密钥

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

使用上面的getKeys()方法,输出应该是:

阵列([0]=>数组([name]=>Arti Luthra博士[电子邮件]=>artiluthra@dsingh.com[地址]=>阵列([0]=>数组([临床名称]=>卢特拉医疗中心[地址]=>A-65/2,Meera Bhagh[timings]=>阵列([0]=>数组([start]=>上午09:00)[1] =>阵列([start]=>05:00 PM)))[1] =>阵列([临床名称]=>卢特拉医疗中心[地址]=>A-65/2,Chanakyapuri[timings]=>阵列([0]=>数组([start]=>上午09:00)))))[1] =>阵列([name]=>Sudhir Seth[电子邮件]=>sudhirseth@gmail.com[地址]=>阵列([0]=>数组([clinical_name]=>Sudhir Seth医生骨科[地址]=>D-595,Chittranjan公园,地标:除德里Deshbandhu学院外[timings]=>阵列([0]=>数组([start]=>上午10:30)[1] =>阵列([start]=>06:00 PM)))[1] =>阵列([临床名称]=>Fortis C-Doc[地址]=>B-16,Chirag Enclave,Nehru Place。地标:Opp.to Nehru Place,德里[timings]=>阵列([0]=>数组([start]=>上午09:00))))))

这个问题似乎非常接近xml结构的xPath。

还有什么有趣的是json的jsonPath,例如:

PHP中的JsonPath-https://github.com/Skyscanner/JsonPath-PHP

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

但是,不幸的是,对于php数组,这项技术还没有实现。

这是编写自己的库(phpPath)的好方法!

特别是关于你的一个有点不同的情况:

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

使用示例:

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

此解决方案将起作用。它调用一个类,该类将创建一个字符串,然后json_decode该字符串来创建您要查找的数组。创建了两个文件,一个包含类,另一个实例化该类中的对象。

ArrayManager.php定义类

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只包含示例数组和调用ArrayManager类的代码。

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;

这个函数应该处理一个由点分隔的单一路径:

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

为了支持多条路径,只需迭代即可:

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

最新更新