Это типичная структура массива:
$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;
}
Ты можешь использовать 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, Итератор а также Счетный сделать изменения полностью прозрачными, и вы сможете реализовать вспомогательные методы, чтобы скрыть сложность извлечения данных.
Вот пример, просто использующий 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;
}
}
Используя приведенный выше код, вы сможете получить доступ к своим данным, как только вы это сделали, но у вас также есть возможность определить дополнительные средства доступа в хорошем контейнере. Обратите внимание, что вы также должны реализовать интерфейс итератора, чтобы иметь возможность просматривать ваши данные.
Это не решает проблему «элегантности» базовой реализации (другие решения хорошо справляются с этим), но этот способ полностью скрывает сложность.