Это типичная структура массива :
$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', ) ));
Вот неэстетичный способ (или «не очень элегантный способ»), чтобы уменьшить большой массив до простого массива, содержащего только один столбец:
$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; }
с$fieldsByName = array(); foreach ($strut['resources'][0]['schema']['fields'] as $r){ $key = $r['name']; unset($r['name']); $fields[$key] = $r; }
Вы можете использовать array_column
для извлечения всех значений с 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: каждое третье значение может быть ключевым значением нового активного массива, которое содержит массив с массивами первых двух значений .. или, как вы пожелаете
array_column – первое логическое объявление, без сюрпризов.
В зависимости от того, насколько нормализованы ваши данные и как часто возникают эти проблемы, вы можете реализовать класс вокруг своих данных. Вы можете использовать ArrayAccess , Iterator и Countable , чтобы сделать изменение полностью прозрачным, и вы сможете реализовать вспомогательные методы, чтобы скрыть сложность выборки данных.
Вот пример, просто используя 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, чтобы иметь возможность отслеживать ваши данные.
Это не относится к проблеме «элегантности» основной реализации (другие решения хорошо справляются с этим), но этот способ полностью скрывает сложность.