2012-01-16 34 views
18

Bạn có thể "change" the key of an array element chỉ đơn giản bằng cách thiết lập phím mới và loại bỏ cái cũ:Thay đổi quan trọng mảng mà không thay đổi trật tự

$array[$newKey] = $array[$oldKey]; 
unset($array[$oldKey]); 

Nhưng điều này sẽ di chuyển chìa khóa dẫn đến cuối mảng.

Có cách nào thanh lịch để thay đổi khóa mà không thay đổi thứ tự không?

(PS: Câu hỏi này chỉ vì lợi ích khái niệm, không phải vì tôi cần nó ở bất cứ đâu.)

+0

Tôi tưởng tượng một số cấu trúc xấu xí với array_splice() và array_slice() sẽ thực hiện thủ thuật –

+0

@MarcB Điều đó sẽ không hoạt động với các phím chuỗi mặc dù. – NikiC

+0

Tôi không phải là một lập trình PHP, nhưng những gì trên thế giới là ngữ nghĩa của '$ arr [$ oldKey]' nếu điều này hoạt động như một đối số cho một hàm loại bỏ '$ oldKey' khỏi' $ arr'? Tôi nghĩ PHP có thể thú vị hơn tôi từng nghĩ, sẽ phải xem xét điều này… –

Trả lời

25

Tested và làm việc :)

$array = array("a" => "1", "b" => "2", "c" => "3"); 

function replace_key($array, $old_key, $new_key) { 
    $keys = array_keys($array); 
    if (false === $index = array_search($old_key, $keys)) { 
     throw new Exception(sprintf('Key "%s" does not exit', $old_key)); 
    } 
    $keys[$index] = $new_key; 
    return array_combine($keys, array_values($array)); 
} 

$new_array = replace_key($array, "b", "e"); 
+0

+1 Mặc dù bạn có lẽ nên thêm một trình xử lý lỗi cho trường hợp '$ old_key' không nằm trong mảng. –

+0

Chỉ khi khóa không tồn tại thì hãy thay thế khóa đầu tiên. Thêm một mệnh đề if, và bạn ok;) – Kristian

+0

Sẽ không tốt hơn khi trả về mảng không thay đổi thay vì ném một ngoại lệ? –

-1

Thực hiện thao tác lật đôi! Ít nhất đó là tất cả tôi có thể nghĩ:

$array=("foo"=>"bar","asdf"=>"fdsa"); 
$array=array_flip($array); 
$array["bar"]=>'newkey'; 
$array=array_flip($array); 
+0

Và đây chỉ là lý thuyết, tôi chưa thử nghiệm xem nó có hoạt động hay không, nhưng tôi tưởng tượng nó sẽ thành công. –

+5

Điều đó sẽ thất bại nếu có giá trị trùng lặp. –

+0

Đúng .... welp, sau đó tôi ra khỏi ý tưởng. –

6

Một cách sẽ được chỉ đơn giản là sử dụng một iterating foreach qua mảng và sao chép nó vào một mảng mới, thay đổi phím điều kiện trong khi lặp lại, ví dụ nếu $ === chìa khóa 'foo' sau đó không sử dụng foo nhưng thanh:

function array_key_rename($array, $oldKey, $newKey) 
{ 
    $newArray = []; 
    foreach ($array as $key => $value) { 
     $newArray[$key === $oldKey ? $newKey : $key] = $value; 
    } 
    return $newArray; 
} 

Một cách khác sẽ được serialize mảng, str_replace phím serialized và sau đó unserialize trở lại vào một mảng một lần nữa. Đó không phải là đặc biệt thanh lịch mặc dù và có khả năng dễ bị lỗi, đặc biệt là khi bạn không chỉ có vô hướng hoặc mảng đa chiều.

Một cách thứ ba - yêu thích của tôi - sẽ được bạn viết array_key_rename trong C và đề nghị nó cho lõi PHP;)

+0

Có phải $ newArray có thể truy cập từ bên ngoài phạm vi của foreach không? – nawfal

+0

@nawfal có, nhưng không phải bên ngoài chức năng trừ khi bạn gán giá trị trả lại – Gordon

+0

OK. Bit lạ để làm quen với PHP đến từ ngôn ngữ khác :) – nawfal

-2

Bạn có thể sử dụng array_combine. Nó kết hợp một mảng cho các phím và một cho các giá trị ...

Ví dụ:

$original_array =('foo'=>'bar','asdf'=>'fdsa'); 
$new_keys  = array('abc', 'def'); 
$new_array  = array_combine($new_keys, $original_array); 
+0

Điều gì sẽ xảy ra nếu bạn có nhiều khóa và chỉ muốn thay đổi một khóa? Với giải pháp của bạn, bạn có nghĩa vụ phải viết một mảng $ new_keys bất tận. –

9

Something như thế này cũng có thể làm việc:

$langs = array("EN" => "English", 
     "ZH" => "Chinese", 
     "DA" => "Danish", 
     "NL" => "Dutch", 
     "FI" => "Finnish", 
     "FR" => "French", 
     "DE" => "German"); 
$json = str_replace('"EN":', '"en":', json_encode($langs)); 
print_r(json_decode($json, true)); 

OUTPUT:

Array 
(
    [en] => English 
    [ZH] => Chinese 
    [DA] => Danish 
    [NL] => Dutch 
    [FI] => Finnish 
    [FR] => French 
    [DE] => German 
) 
+6

Cá nhân tôi thấy giải pháp này rất thanh lịch! +1 –

+3

Tôi cũng thế. Điều này làm việc tuyệt vời để loại bỏ dấu gạch ngang/dấu gạch dưới từ tên thẻ XML khi sử dụng Zend_Config_XML :: toArray(). Trong trường hợp của tôi, dữ liệu là tùy chọn cho các phần tử được chọn w/optgroups. Tên optgroup của tôi là các thẻ XML, và các tiêu đề có dấu gạch ngang. Điều này làm việc tốt cho điều đó. – axiom82

+3

Tôi không thấy trang nhã này. Rất nguy hiểm. – nawfal

0

Chúng tôi đang sử dụng chức năng này để thay đổi nhiều khóa mảng trong một rray giữ trật tự:

function replace_keys($array, $keys_map) { 
    $keys = array_keys($array); 
    foreach($keys_map as $old_key=>$new_key){ 
     if (false === $index = array_search($old_key, $keys)) { 
      continue; 
     } 
     $keys[$index] = $new_key; 
    } 
    return array_combine($keys, array_values($array)); 
} 

Bạn có thể vượt qua một mảng như $ keys_map, như thế này:

$keys_map=array("old_key_1"=>"new_key_1", "old_key_2"=>"new_key_2",...) 

giải pháp này được dựa trên Kristian một.

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