2009-12-10 41 views
8

Dưới đây là một mảng Ví dụ:PHP chuyển đổi mảng lồng nhau thành mảng đơn trong khi ghép nối các khóa?

$foo = array(
      'employer' => array(
        'name' => 'Foobar Inc', 
        'phone' => '555-555-5555' 
        ), 
      'employee' => array(
        'name' => 'John Doe', 
        'phone' => '555-555-5556', 
        'address' => array(
          'state' => 'California', 
          'zip' => '90210' 
         ) 
        ), 
      'modified' => '2009-12-01', 
     ); 

Và tôi muốn để có được một kết quả như thế này:

$fooCompressed = array(
      'employer_name' => 'Foobar Inc', 
      'employer_phone' => '555-555-5555', 
      'employee_name' => 'John Doe', 
      'employee_phone' => '555-555-5556' 
      'employee_address_state' => 'California', 
      'employee_address_zip' => '90210', 
      'modified' => '2009-12-01' 
      ) 

Làm thế nào tôi sẽ đi về cách viết một hàm đệ quy để xử lý này?

Trả lời

13

Something như thế này:

function makeNonNestedRecursive(array &$out, $key, array $in){ 
    foreach($in as $k=>$v){ 
     if(is_array($v)){ 
      makeNonNestedRecursive($out, $key . $k . '_', $v); 
     }else{ 
      $out[$key . $k] = $v; 
     } 
    } 
} 

function makeNonNested(array $in){ 
    $out = array(); 
    makeNonNestedRecursive($out, '', $in); 
    return $out; 
} 

// Example 
$fooCompressed = makeNonNested($foo); 
+0

+1 này là khá gần với những gì tôi muốn làm. Bởi vì các phím đang được sửa đổi, không có chức năng tích hợp sẽ làm điều đó cho bạn, và bạn chắc chắn cần đệ quy để đi sâu vào bất kỳ giá trị phụ nào cũng là mảng. – zombat

+0

ví dụ điển hình. Tôi thích ý tưởng truyền mảng đầu ra theo tham chiếu. – GSto

3

Đây là một chức năng cho phép bạn chỉ định một tiền tố cấp cao thông qua các tham số thứ hai:

function flatten_array($array, $prefix = null) { 
    if ($prefix) $prefix .= '_'; 

    $items = array(); 

    foreach ($array as $key => $value) { 
    if (is_array($value)) 
     $items = array_merge($items, flatten_array($value, $prefix . $key)); 
    else 
     $items[$prefix . $key] = $value; 
    } 

    return $items; 
} 
0
/** 
* Flatten a multi-dimensional array or a nested object, constructing concatenated keys for 
* nested elements. 
* @param array or object $array - the array or object to be flattened 
* @param array or string $key_path - current parent keys path. 
* Pass this parameter as string if you need to set a common prefix for all keys 
* @param string $level_separator - keys concatenation glue 
* @param array $flat - resulting flattened array (omit this parameter when calling the function) 
* @return single-dimensional array with all array keys as concatenated keys of elements' 
* paths through the data structure 
*/ 
function flattenArray($array, &$key_path = array(), $level_separator = '.', &$flat = array()) 
{ 
     if(!is_array($key_path)) 
     { 
      // sanitize key_path 
      $key_path = array((string)$key_path); 
     } 
     foreach($array as $key => $value) 
     { 
      // push current key to path 
      array_push($key_path, $key); 

      if(is_array($value) || is_object($value)) 
      { 
       // next level recursion 
       $flat = array_merge($flat, flattenArray($value, $key_path, $level_separator, $flat)); 
      } 
      else 
      { 
        // write the value directly 
        $flat[implode($level_separator, $key_path)] = $value; 
       } 

       // remove used key 
       array_pop($key_path); 
     } 

     return $flat; 
    } 
0

Sau một vài lần lặp lại, tôi đã có thể tinh chỉnh một giải pháp cho vấn đề này sử dụng một phương pháp dựa trên ngăn xếp để tránh đệ quy, đơn giản hóa mọi thứ một chút.

/*** 
* @name array_flatten 
* @author Tom Penzer @tpenzer 
* Flattens a multi-tiered array into a single-tiered 
* associative array with keys reflective of their 
* values' hierarchy. 
* 
* @param array $array  Required - the multi- 
* level keyed array to be flattened 
* @param string $separator Optional - the string 
* used to separate the keys from different levels of 
* the hierarchy 
* 
* @return array a single-level keyed array 
***/ 
function array_flatten($array, $separator = '_') { 
    $output = array(); 

    while (list($key, $value) = each($array)) { 
     if (is_array($value)) { 
      $build = array(); 
      foreach ($value as $s_key => $s_value) { 
       $build[$key . $separator . $s_key] = $s_value; 
      } 
      unset($array[$key]); 
      $array = $build + $array; 
      unset($build); 
      continue;//skip write to $output 
     } 
     $output[$key] = $value; 
     unset($array[$key]); 
    } 

    return $output; 
} 

Không chính xác phương pháp được yêu cầu, nhưng nó tương phản tốt với cách tiếp cận đệ quy cho sự cố.

3

Tôi nghĩ rằng đây 'lừa' sử dụng là http_build_query là ít hơn của một chướng mắt w/out đệ quy (hoặc ít nhất là để cho php làm điều đó cho bạn)

3 dòng mã nếu str_replace của bạn sử dụng các giá trị url-mã hóa cho [và]

$string  = http_build_query($array); 
$string  = urldecode($string); 
$string  = str_replace(
        array('[',']'), 
        array('_','') , 
        $string 
       ); 
parse_str($string, $flat_array); 

$ flat_array trở thành:

array(7) { 
    ["employer_name"]   =>"Foobar Inc" 
    ["employer_phone"]  =>"555-555-5555" 
    ["employee_name"]   =>"John Doe" 
    ["employee_phone"]  =>"555-555-5556" 
    ["employee_address_state"]=>"California" 
    ["employee_address_zip"] =>"90210" 
    ["modified"]    =>"2009-12-01" 
} 
Các vấn đề liên quan