2015-03-22 14 views
8

To a typical array structure:Czy istnieje elegancki sposób na zredukowanie struktury do prostej tablicy?

$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', 
    ) 
)); 

Oto non-elegancki sposób (lub "nie tak elegancki sposób"), aby zmniejszyć dużą tablicę do prostego tablicę zawierającą tylko jedną kolumnę:

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

To działa, ale czy można zrobić to samo za pomocą tylko jednej instrukcji? Być może używając jak array_reduce(), ale nie widzę jak.


Oto inny "problem elegancja PHP" typowy:

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

Czy istnieje alternatywa PHP? Chodzi o to, aby użyć słowa kluczowego (name w przykładzie) jako klucz tablicy i inne elementy jak zwykle pól, tak, rodzajowy non-elegancki algorytm jest

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

Odpowiedz

5

Można użyć array_column aby wyodrębnić wszystkie wartości z klucza name do innej tablicy

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

Zgadzam się z tobą ,, powinniśmy uprościć problem, tak jak potrzebujemy wszystkich tablic podrzędnych wewnątrz głównej tablicy, która ma "imię" jako klucz –

+0

dzięki, byłeś szybki i precyzyjny (!) ... Jakiś dobry trop do drugi problem? –

+0

@PeterKrauss Drugi problem będzie wymagać więcej wywołań funkcji ... nie ma nic wbudowanego tylko do tego. Ale ładną jedną linijką byłoby '$ fields = array_combine (array_column ($ your_array, 'name'), array_map (function ($ array) {return array_diff_key ($ array, [" name "=> 1]);}, $ your_array)); '. - I tak ... musisz iterować w jakiś sposób przez tę tablicę ... przez foreach lub tablicę_mapową ... nie ma znaczenia. Nie ma nic wbudowanego, aby uzyskać tablicę bez określonego klucza (np. Kolumna_kolumna, tylko że nie zwraca ona całego tego indeksu, ale wszystkie bez tego indeksu). W tym przypadku jesteś naprawdę lepszy dzięki foreach ... – bwoebi

2

można umieścić tablicę thru tej funkcji:

function flatten(array $array) { 
$return = array(); 
array_walk_recursive($array, function($a) use (&$return) { $return[] = $a; }); 
return $return; 
} 

spowoduje to tylko literalną sekwencję prawidłowych wartości wielowymiarowej tablicy, jak na przykład.

Array 
(
    [0] => etc 
    [1] => year 
    [2] => Year of ... 
    [3] => integer 
    [4] => day 
    [5] => Day of the ... 
    [6] => string 
    [7] => xx 
    [8] => Xx ... 
    [9] => string 
) 

następnie, jak wiadomo, oryginalną strukturę - można przeanalizować, jak potrzebne. 4ex: co trzecia wartość może być nową wartością tablicy tablicy asocjacyjnej, która zawiera tablicę z tablicami pierwszych dwóch wartości .. lub, jeśli chcesz,

array_column jest pierwszym logicznym ogłoszeniem, bez niespodzianek.

+0

Dobre wskazówki (!), czy możesz zilustrować rozwiązanie z (rozwiązaniem) mojego problemu '$ fieldsByName'? –

2

W zależności od tego, jak znormalizowane są Twoje dane i jak często pojawiają się problemy, możesz zaimplementować klasę wokół danych. Można użyć wartości ArrayAccess, Iterator i Countable, aby zmiana była całkowicie przezroczysta, a użytkownik mógłby implementować metody pomocnicze w celu ukrycia złożoności pobierania danych.

Oto przykład, tylko przy użyciu 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; 
    } 

} 

Stosując powyższy kod powinien być w stanie uzyskać dostęp do swoich danych po prostu nie byliście, ale masz również możliwość definiowania dodatkowych akcesorów w sposób ładny pojemnik. Zwróć uwagę, że musisz również wdrożyć interfejs Iteratora, aby móc wykluczyć dane.

Nie odnosi się to do kwestii "elegancji" podstawowej realizacji (inne rozwiązania sprawiają się dobrze), ale w ten sposób całkowicie ukrywa złożoność.

+0

Tak," ukryj złożoność "w bibliotece lub strukturze to również dobry pomysł, ale moje pierwsze zainteresowanie dotyczyło wbudowanych rozwiązań PHP (zobacz' array_column() '!) ... Więc jeśli PHP nie ma rozwiązania (czy masz trochę do drugiego problemu?), To musimy odwołać się do biblioteki, wyrażonej w eleganckiej klasie, tak jak sugerujesz. –