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

时间:2015-03-22 22:02:45

标签: php data-structures

这是a typical array structure

$s = array ('etc'=>'etc', 'fields' => 
  array (
   0 => array (
     'name'=>'year', 'description'=>'Year of ...', 'type'=>'integer',
   ),
   1 =>  array (
     'name'=>'label', 'description'=>'Offical short name', type'=>'string',
   ),
   2 => array (
     'name' => 'xx', 'description' => 'Xx ...', 'type' => 'string',
   )
 ));

这是一种非优雅的方式(或者#34;不那么优雅的方式")将大数组缩减为只包含一列的简单数组:

 $fields = array();
 foreach ($strut['resources'][0]['schema']['fields'] as $r)
    $fields[] = $r['name'];

这有效,但是只用一条指令就可以做同样的事吗?也许使用类似array_reduce(),但我不知道如何。


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

 $fieldsByName = array();
 foreach ($strut['resources'][0]['schema']['fields'] as $r)
    $fields[$r['name']] = array(
        'description' =>$r['description'],
        'type' =>$r['type']
    );

是否有PHP备选方案?这里的想法是使用关键字(示例中为name)作为数组键,其他元素作为常用字段,因此,通用非优雅算法是

 $fieldsByName = array();
 foreach ($strut['resources'][0]['schema']['fields'] as $r){
    $key = $r['name'];
    unset($r['name']);
    $fields[$key] = $r;
 }

3 个答案:

答案 0 :(得分:5)

您可以使用array_column将密钥name的所有值提取到另一个数组

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

答案 1 :(得分:2)

你可以通过这个函数放置你的数组:

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:每三个值可以是新的关联数组的键值,它包含一个包含前两个值的数组的数组..或者你想要的

array_column是第一个逻辑公告,没有惊喜。

答案 2 :(得分:2)

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

这是一个例子,只使用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;
    }

}

使用上面的代码,您应该能够访问您的数据,但您也可以选择在一个漂亮的容器中定义其他访问者。请注意,您还必须实现Iterator接口,以便能够预测数据。

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