Есть ли элегантный способ уменьшить структуру до простого массива?

Это типичная структура массива:

$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;
}

8

Решение

Ты можешь использовать array_column извлечь все значения с ключом name в другой массив

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

Другие решения

Вы можете поместить свой массив через эту функцию:

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

В зависимости от того, насколько нормализованы ваши данные и как часто возникают эти проблемы, вы можете реализовать класс вокруг ваших данных. Вы можете использовать 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;
}

}

Используя приведенный выше код, вы сможете получить доступ к своим данным, как только вы это сделали, но у вас также есть возможность определить дополнительные средства доступа в хорошем контейнере. Обратите внимание, что вы также должны реализовать интерфейс итератора, чтобы иметь возможность просматривать ваши данные.

Это не решает проблему «элегантности» базовой реализации (другие решения хорошо справляются с этим), но этот способ полностью скрывает сложность.

2
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector