我正在使用Oxford Dictionary API来查找单词定义。返回的JSON可能是13级或更高级别。它是对象的数组,我永远无法确定任何一个对象都会存在。
我想返回一个简单的定义数组,存储在$list
。
所以我发现自己写了这个恐怖故事:
$list = [];
$data = json_decode( $response->getBody() );
//oh gross
if( isset( $data->results ) ) {
foreach( $data->results as $r ) {
if( isset( $r->lexicalEntries ) ) {
foreach( $r->lexicalEntries as $l ) {
if( isset( $l->entries ) ) {
foreach( $l->entries as $e ) {
if( isset( $e->senses ) ) {
foreach( $e->senses as $s ) {
if( isset( $s->definitions ) ) {
foreach( $s->definitions as $d ) {
$list[] = [
'word' => $r->word,
'definition' => $d
];
}
}
if( isset( $s->subsenses ) ) {
foreach( $s->subsenses as $ss ) {
if( isset( $ss->definitions ) ) {
foreach( $ss->definitions as $d ) {
$list[] = [
'word' => $r->word,
'definition' => $d
];
}
}
}
}
}
}
}
}
}
}
}
}
return $list;
哪个有效,但只是完全讨厌。
我考虑过递归函数,但不确定它是否更具可读性。
有更优雅的方式吗?
答案 0 :(得分:2)
嗯,我必须说实话,因为你的方法的结果只是一个包含两个索引的数组,其中word
总是相同的而definition
是不同的。如果你真的希望$r->word
与definition
一起存储,那么几乎无法做到。
但是,您可以使用以下代码缩短isset()
代码
两个版本的例子:
// PHP < 7.
foreach(isset($data['results']) ? $data['results'] : [] as $value){}
// PHP > 7
foreach($data['results'] ?? [] as $value){}
但是,这只是为了抑制错误报告,您可以暂时将其关闭并重新打开,只是假设索引存在并忘记isset()
。
我已经定义了这样的数据:
$json = file_get_contents('data.json');
$data = json_decode($json, true);
在这种情况下,我更喜欢对象的数组,以及使用PHP 7 null coalesce运算符处理方法的副本:
foreach($data['results'] ?? [] as $r){
foreach($r['lexicalEntries'] ?? [] as $l){
foreach($l['entries'] ?? [] as $e){
foreach($e['senses'] ?? [] as $s){
foreach( $s['definitions'] ?? [] as $d){
$list[] = [
'word' => $r['word'],
'definition' => $d
];
}
foreach($s['subsenses'] ?? [] as $ss){
foreach( $ss['definitions'] ?? [] as $d){
$list[] = [
'word' => $r['word'],
'definition' => $d
];
}
}
}
}
}
}
print_r($list);
但是,还有其他方法可以做到这一点,那就是展平数组。有多种方法可以做到这一点,我更喜欢生成器,但在PHP 7及更高版本中引入了递归生成器。
// This is a generator function, it flattens the entire given array.
// It yields an array containing the key and value on each iteration.
function array_walk_generator($array){
foreach($array as $k => $v){
yield $k => $v;
if(is_array($v)){
yield from array_walk_generator($v);
}
}
}
foreach($data['results'] as $result){
$list = [];
foreach(array_walk_generator($result) as $k => $v){
if($k == 'definitions' && is_array($v)){
$list[] = $v[0];
}
}
$return[] = [
'word' => $result['word'],
'definitions' => array_values(array_filter($list))
];
}
print_r($return);
这样你就可以看到一个更有组织的数组,这种方式并不关心定义的格式。