2012-11-07 25 views
16

Tôi đang sử dụng các hàm mảng để chuyển đổi chuỗi phân tách đường ống của tôi thành một mảng kết hợp.thay đổi các phím mảng trong hàm array_walk?

$piper = "|k=f|p=t|e=r|t=m|"; 

$piper = explode("|",$piper); 

$piper = array_filter($piper); 

function splitter(&$value,$key) { 

    $splitted = explode("=",$value); 
    $key = $splitted[0]; 
    $value = $splitted[1]; 

} 

array_walk($piper, 'splitter'); 

var_dump($piper); 

này mang lại cho tôi

array (size=4) 
    1 => string 'f' (length=1) 
    2 => string 't' (length=1) 
    3 => string 'r' (length=1) 
    4 => string 'm' (length=1) 

nơi mà tôi muốn:

array (size=4) 
    "k" => string 'f' (length=1) 
    "p" => string 't' (length=1) 
    "e" => string 'r' (length=1) 
    "t" => string 'm' (length=1) 

nhưng các phím là không thay đổi gì. Có chức năng mảng nào mà tôi có thể lặp qua một mảng và thay đổi các khóa và giá trị không?

+0

gì là mảng kết quả mong muốn? –

+0

@JasonMcCreary: tôi đã cập nhật nó – mithunsatheesh

+2

Bản chỉnh sửa: "Nhanh nhất" làm cho câu hỏi này không phải là một câu hỏi mang tính xây dựng trong mắt tôi. Xem bình luận của tôi dưới đây. – hakre

Trả lời

43

Người ta nói trong tài liệu của array_walk (mô tả các hàm callback):

Chỉ các giá trị của mảng có khả năng có thể thay đổi; cấu trúc của nó không thể thay đổi, tức là, người lập trình không thể thêm, bỏ đặt hoặc sắp xếp lại các yếu tố . Nếu cuộc gọi lại không tôn trọng yêu cầu này, hành vi của chức năng này không được xác định và không thể đoán trước.

Điều đó có nghĩa là bạn không thể sử dụng array_walk để thay đổi các khóa của mảng được lặp lại. Bạn có thể, tuy nhiên, tạo ra một mảng mới với nó:

$result = array(); 
array_walk($piper, function (&$value,$key) use (&$result) { 
    $splitted = explode("=",$value); 
    $result[ $splitted[0] ] = $splitted[1]; 
}); 
var_dump($result); 

Tuy nhiên, tôi nghĩ rằng nếu nó đã được tôi, tôi muốn sử dụng regex đây (thay vì "nổ phát nổ"):

$piper = "|k=f|p=t|e=r|t=m|"; 
preg_match_all('#([^=|]*)=([^|]*)#', $piper, $matches, PREG_PATTERN_ORDER); 
$piper = array_combine($matches[1], $matches[2]); 
var_dump($piper); 
+2

+1 cho 'use'. Lời nhắc này yêu cầu PHP 5.3+. –

+0

Vâng, đây là chi phí so với một lặp đi lặp lại foreach đơn giản mà đã có mã và không cần phải vượt qua các biến trên phạm vi. – hakre

+0

tại sao bạn sẽ sử dụng array_walk và không phải là một foreach đơn giản cho mục đích này? –

2

Bạn có thể sử dụng tốt hơn foreach cho điều đó. Ví dụ sau đây cho thấy việc xử lý một mục nhập, thêm nó vào đúng khóa và xóa mục nhập ban đầu.

$piper = "|k=f|p=t|e=r|t=m|"; 
$piper = array_filter(explode("|", $piper)); 

foreach ($piper as $index => $value) { 
    list($key, $value) = explode("=", $value); 
    $piper[$key] = $value; 
    unset($piper[$index]); 
} 

Cẩn thận bạn không có khóa giống như chỉ mục.

lựa chọn khác là để xử lý các giá trị thông qua một tài liệu tham khảo và thiết lập các phím sau:

foreach ($piper as &$value) { 
    list($keys[], $value) = explode("=", $value); 
} 
unset($value); 

$piper = array_combine($keys, $piper); 

này không mang lại cho bạn vào bất kỳ khó khăn nhưng chỉ với các phím trùng lặp. Nhưng bạn có thể kiểm tra vấn đề đó sau foreach, không có dữ liệu nào bị mất.

Cái gì đó không được đảm bảo như sau foreach mà có lẽ là đơn giản nhất bởi stroing thành một mảng kết quả:

$result = array(); 
foreach ($piper as $value) { 
    list($key, $value) = explode("=", $value); 
    $result[$key] = $value; 
} 
+0

Tại sao tái sử dụng '$ piper'? –

+1

@JasonMcCreary: Tôi đã thêm một ví dụ thứ hai sử dụng lại giá trị phù hợp hơn. Trong mọi trường hợp '$ piper' là để xử lý vì vậy tôi không thấy bất kỳ vấn đề nào để sử dụng (không sử dụng lại) nó. – hakre

+0

hãy gợi ý cho tôi cái nào sẽ thực thi nhanh nhất? foreach hoặc regex hay là array_walk? – mithunsatheesh

3

Tại sao không xây dựng một mảng mới có các phím mong muốn và giá trị từ $ thổi sáo ?

$piper2 = array(); 
foreach ($piper as $k => $val) 
{ 
    $splitted = explode("=", $val); 
    $key = $splitted[0]; 
    $value = $splitted[1]; 

    $piper2[$key] = $value; 
} 

$piper = $piper2; // if needed 
+0

hãy gợi ý cho tôi cái nào sẽ thực thi nhanh nhất? foreach hoặc regex hay là array_walk? – mithunsatheesh

0

Sử dụng array_reduce sẽ làm các trick

$piper = "|k=f|p=t|e=r|t=m|"; 

$piper = explode("|",$piper); 

$piper = array_filter($piper); 

function splitter($result, $item) { 
    $splitted = explode("=",$item); 
    $key = $splitted[0]; 
    $value = $splitted[1]; 

    $result[$key] = $value; 

    return $result; 
} 

$piper = array_reduce($piper, 'splitter', array()); 

var_dump($piper); 

dựa trên này: http://www.danielauener.com/howto-use-array_map-on-associative-arrays-to-change-values-and-keys/

Các vấn đề liên quan