Php 有没有一种优雅的方法可以将结构简化为一个简单的数组?

Php 有没有一种优雅的方法可以将结构简化为一个简单的数组?,php,data-structures,Php,Data Structures,这是: $s=array('etc'=>'etc','fields'=> 排列( 0=>数组( 'name'=>'year','description'=>'year of…','type'=>'integer', ), 1=>数组( 'name'=>'label','description'=>'office short name',键入'=>'string', ), 2=>数组( “名称”=>“xx”,“说明”=>“xx…”,“类型”=>“字符串”, ) )); 以下是一种非优雅的方式(或

这是:

$s=array('etc'=>'etc','fields'=>
排列(
0=>数组(
'name'=>'year','description'=>'year of…','type'=>'integer',
),
1=>数组(
'name'=>'label','description'=>'office short name',键入'=>'string',
),
2=>数组(
“名称”=>“xx”,“说明”=>“xx…”,“类型”=>“字符串”,
)
));
以下是一种非优雅的方式(或“不那么优雅的方式”)将大数组简化为只包含一列的简单数组:

$fields=array();
foreach($r形式的struts['resources'][0]['schema']['fields']
$fields[]=$r['name'];
这是可行的,但是否可以只使用一条指令就实现同样的功能?可能使用类似于
array\u reduce()
,但我不知道如何使用


以下是其他典型的“优雅PHP问题”:

$fieldsByName=array();
foreach($r形式的struts['resources'][0]['schema']['fields']
$fields[$r['name']]=数组(
'description'=>r$r['description'],
'type'=>r$r['type']
);
有PHP替代方案吗?这里的想法是使用关键字(
示例中的name
)作为数组键,其他元素作为常规字段,因此,通用的非优雅算法是

$fieldsByName=array();
foreach($r形式的struts['resources'][0]['schema']['fields']{
$key=$r['name'];
未结算($r['name']);
$fields[$key]=$r;
}
您可以使用将键
name
的所有值提取到另一个数组中

$names = array_column($strut['resources'][0]['schema']['fields'], 'name');

您可以通过以下功能放置阵列:

function flatten(array $array) {
$return = array();
array_walk_recursive($array, function($a) use (&$return) { $return[] = $a; });
return $return;
}
它将只产生一个由多维数组的值组成的文本序列,如下所示

Array
(
    [0] => etc
    [1] => year
    [2] => Year of ...
    [3] => integer
    [4] => day
    [5] => Day of the ...
    [6] => string
    [7] => xx
    [8] => Xx ...
    [9] => string
)
然后,正如您知道的原始结构一样,您可以根据需要解析它。4ex:每三个值可以是新的assoc数组的键值,该键值包含具有前两个值的数组的数组..,或者如您所愿


array_列是第一个合乎逻辑的声明,这并不奇怪。

根据数据的规范化程度以及出现此问题的频率,您可以围绕数据实现一个类。您可以使用和使更改完全透明,并且可以实现帮助器方法来隐藏获取数据的复杂性

以下是一个仅使用ArrayAccess的示例:

class Strut implements ArrayAccess {

    private $data;
    private $fieldsByName = null;

    public function __construct($data) {
        $this->data = $data;
    }

    public function fieldsByName() {
        //If the result has not already been computed
        if($this->fieldsByName === null) {
            $this->fieldsByName = array();
            foreach($this->data['resources'][0]['schema']['fields'] as $r) {
                $this->fieldsByName[ $r['name'] ] = array(
                    'description' =>$r['description'],
                    'type' =>$r['type']
                );
            }
        }

        return $this->fieldsByName;
    }

    /**
     * ArrayAccess Methods
     */
    public function offsetSet($offset, $value) {
        $this->data[$offset] = $value;
    }

    public function offsetExists($offset) {
        return isset( $this->data[$offset] );
    }

    public function offsetUnset($offset) {
        unset( $this->data[$offset] );
    }

    public function offsetGet($offset) {
        return isset( $this->data[$offset] ) ? $this->data[$offset] : null;
    }

}
使用上面的代码,您应该能够访问数据,但您也可以选择在一个漂亮的容器中定义其他访问器。请注意,您还必须实现迭代器接口才能对数据进行foreach


这并没有解决底层实现的“优雅”问题(其他解决方案在这方面做得很好),但这种方法完全隐藏了复杂性。

我同意你的观点,我们应该简化这个问题,就像我们需要主数组中所有的子数组一样,主数组中的“name”是一个键谢谢,你快速准确(!)。。。第二个问题有什么好的线索吗?@PeterKrauss第二个问题需要更多的函数调用……没有什么内置的东西可以解决这个问题。但是一个好的单行程序应该是
$fields=array\u combine(array\u column($your\u array,'name')),array\u map(function($array){return array\u diff\u key($array,[“name”=>1]),$your\u array))-是的…你需要通过foreach或array_map在数组上迭代…这不重要。没有任何内置功能可以获取没有特定键的数组(比如array_列,只是它不会返回该索引的所有内容,而是返回没有该索引的所有内容)。在这种情况下,使用foreach会更好…@bwoebi,谢谢(!),也许Python有比PHP更优雅的东西:-)是的,一些
foreach
与“array\u数组的组合、array的列、array的映射、array\u diff\u键”相比可能更优雅。。。它是PHP。。。您的解决方案没有未设置($r['name'])
是很好的(!),可能对其他读者有用:
$x0=array\u组合(array\u列($strub['x'][0],'name')、array\u diff\u键($strub['x'][0],'name'=>1])
很好的线索(!),您能用(解决)我的
$fieldsByName
问题来说明解决方案吗?是的,“隐藏复杂性”在库或框架中也是一个好主意,但我的第一个兴趣是PHP内置解决方案(请参见
array\u column()
!)…因此,如果PHP没有解决方案(您有解决第二个问题的方法吗?),那么我们必须求助于库,按照您的建议用优雅的类表示。