PHP에서 배열 요소의 키를 어떻게 변경합니까?


348

key => value키가 숫자 값인 형식의 연관 배열이 있지만 순차 숫자 값이 아닙니다. 키는 실제로 ID 번호이고 값은 개수입니다. 이것은 대부분의 경우에 적합하지만 값을 변경하지 않고 사람이 읽을 수있는 배열의 이름을 가져 와서 키에 사용하는 함수를 원합니다.

나는 이것을하는 함수를 보지 못했지만 이전 키와 새 키 (둘 다 가지고 있음)를 제공하고 배열을 변환해야한다고 가정합니다. 이를 수행하는 효율적인 방법이 있습니까?


답변:


576
$arr[$newkey] = $arr[$oldkey];
unset($arr[$oldkey]);

5
1) 사람이 읽을 수있는 동일한 버전을 가진 두 개의 키는 없습니다. 2) 사람이 읽을 수있는 버전은 숫자가 아닙니다.
Greg

81
또한 이것은 아마도 배열의 순서를 바꿀 것이므로 조심해야 할 수도 있습니다. PHP의 연관 배열조차도 주문되며 때로는 그 순서가 활용됩니다.
Robin Winslow

7
그래, 좋은 지적이야 로빈 동일한 주문을 유지하는 방법이 있습니까? 아니면 그것을 달성하기 위해 새로운 배열을 만들어야합니까?
Simon East

40
보너스 질문 : ID를 변경하고 배열 순서를 유지하는 방법은 무엇입니까?
Petr Peller

17
키 값이 변경되지 않으면 배열 요소가 삭제됩니다. 확인하고 싶을 수도 있습니다.
Peeech

97

이 작업을 수행하고 배열 순서를 유지하는 방법은 배열 키를 별도의 배열에 넣고 해당 배열의 키를 찾아서 바꾸고 값과 다시 결합하는 것입니다.

다음과 같은 기능이 있습니다.

function change_key( $array, $old_key, $new_key ) {

    if( ! array_key_exists( $old_key, $array ) )
        return $array;

    $keys = array_keys( $array );
    $keys[ array_search( $old_key, $keys ) ] = $new_key;

    return array_combine( $keys, $array );
}

2
덕분에 배열의 순서를 유지해야했기 때문에 정말 도움이되었습니다. 이 페이지를 찾기 전에 이미 수락 된 답변을 시도했습니다.
gillytech

3
예, 배열의 순서를 유지하는 것이 더 좋습니다.
Phil Cook

2
중요한 순서를 지키기 위해 좋은 것이 매력처럼 일했습니다!
Learner

: 당신이 공연 또는 주문 보존하려면 마음 stackoverflow.com/a/58619985/1617857
레우 Benoist이를

54

당신이 경우 array데이터베이스 쿼리에서 구축, 당신은에서 직접 키를 변경할 수 있습니다 mysql문 :

대신에

"select ´id´ from ´tablename´..."

다음과 같은 것을 사용하십시오 :

"select ´id´ **as NEWNAME** from ´tablename´..."

좋은 답변, 매우 귀중한!
DevMoutarde 13:21에

20

KernelM의 대답은 훌륭하지만 주석 (충돌 키)에서 Greg가 제기 한 문제를 피하기 위해 새로운 배열을 사용하는 것이 더 안전합니다

$newarr[$newkey] = $oldarr[$oldkey];
$oldarr=$newarr;
unset($newarr);

배열의 크기가 적당한 한 좋은 솔루션입니다. 배열이 사용 가능한 PHP 메모리의 절반 이상을 소비하면 작동하지 않습니다.
kingjeffrey

12
@kingjeffrey, 실제로는 아닙니다. 배열 값은 수정하지 않고 "방금 복사 된"한 복제되지 않습니다. 예를 들어, 10,000 개의 요소를 포함하고 40MB의 메모리를 소비하는 하나의 배열이있는 경우이를 복사하면 값의 사본이 아닌 기존 값에 대한 10,000 개의 참조 만 저장하는 데 필요한 메모리가 소비 되므로 1 개의 배열이 40MB를 소비하는 경우 0.5MB를 소비 할 수 있습니다 (테스트 된).
binaryLV

17

사람이 읽을 수있는 이름을 ID에 매핑하는 두 번째 연관 배열을 사용할 수 있습니다. 그것은 또한 다 대 1 관계를 제공 할 것입니다. 그런 다음 다음과 같이하십시오.

echo 'Widgets: ' . $data[$humanreadbleMapping['Widgets']];

11

새 배열 키의 위치를 ​​이전 배열 키와 동일하게하려면 다음을 수행하십시오.

function change_array_key( $array, $old_key, $new_key) {
    if(!is_array($array)){ print 'You must enter a array as a haystack!'; exit; }
    if(!array_key_exists($old_key, $array)){
        return $array;
    }

    $key_pos = array_search($old_key, array_keys($array));
    $arr_before = array_slice($array, 0, $key_pos);
    $arr_after = array_slice($array, $key_pos + 1);
    $arr_renamed = array($new_key => $array[$old_key]);

    return $arr_before + $arr_renamed + $arr_after;
}

7

배열이 재귀 적 인 경우이 기능을 사용할 수 있습니다.이 데이터를 테스트하십시오.

    $datos = array
    (
        '0' => array
            (
                'no' => 1,
                'id_maquina' => 1,
                'id_transaccion' => 1276316093,
                'ultimo_cambio' => 'asdfsaf',
                'fecha_ultimo_mantenimiento' => 1275804000,
                'mecanico_ultimo_mantenimiento' =>'asdfas',
                'fecha_ultima_reparacion' => 1275804000,
                'mecanico_ultima_reparacion' => 'sadfasf',
                'fecha_siguiente_mantenimiento' => 1275804000,
                'fecha_ultima_falla' => 0,
                'total_fallas' => 0,
            ),

        '1' => array
            (
                'no' => 2,
                'id_maquina' => 2,
                'id_transaccion' => 1276494575,
                'ultimo_cambio' => 'xx',
                'fecha_ultimo_mantenimiento' => 1275372000,
                'mecanico_ultimo_mantenimiento' => 'xx',
                'fecha_ultima_reparacion' => 1275458400,
                'mecanico_ultima_reparacion' => 'xx',
                'fecha_siguiente_mantenimiento' => 1275372000,
                'fecha_ultima_falla' => 0,
                'total_fallas' => 0,
            )
    );

기능은 다음과 같습니다.

function changekeyname($array, $newkey, $oldkey)
{
   foreach ($array as $key => $value) 
   {
      if (is_array($value))
         $array[$key] = changekeyname($value,$newkey,$oldkey);
      else
        {
             $array[$newkey] =  $array[$oldkey];    
        }

   }
   unset($array[$oldkey]);          
   return $array;   
}

7
$array = [
    'old1' => 1
    'old2' => 2
];

$renameMap = [
    'old1' => 'new1',   
    'old2' => 'new2'
];

$array = array_combine(array_map(function($el) use ($renameMap) {
    return $renameMap[$el];
}, array_keys($array)), array_values($array));

/*
$array = [
    'new1' => 1
    'new2' => 2
];
*/

3
나는 배열 함수를 좋아한다. 나는 이것을 모든 키의 이름을 바꾸고 배열 순서를 유지하는 멋진 원 라이너로 제안하려고했지만 대신 당신의 것을 권장합니다.
가을 레너드

6

KernelM의 솔루션이 마음에 들지만 잠재적 인 키 충돌을 처리 할 수있는 것이 필요했습니다 (새 키가 기존 키와 일치 할 수 있음). 다음은 내가 생각해 낸 것입니다.

function swapKeys( &$arr, $origKey, $newKey, &$pendingKeys ) {
    if( !isset( $arr[$newKey] ) ) {
        $arr[$newKey] = $arr[$origKey];
        unset( $arr[$origKey] );
        if( isset( $pendingKeys[$origKey] ) ) {
            // recursion to handle conflicting keys with conflicting keys
            swapKeys( $arr, $pendingKeys[$origKey], $origKey, $pendingKeys );
            unset( $pendingKeys[$origKey] );
        }
    } elseif( $newKey != $origKey ) {
        $pendingKeys[$newKey] = $origKey;
    }
}

그런 다음 다음과 같이 배열을 순환 할 수 있습니다.

$myArray = array( '1970-01-01 00:00:01', '1970-01-01 00:01:00' );
$pendingKeys = array();
foreach( $myArray as $key => $myArrayValue ) {
    // NOTE: strtotime( '1970-01-01 00:00:01' ) = 1 (a conflicting key)
    $timestamp = strtotime( $myArrayValue );
    swapKeys( $myArray, $key, $timestamp, $pendingKeys );
}
// RESULT: $myArray == array( 1=>'1970-01-01 00:00:01', 60=>'1970-01-01 00:01:00' )

6

이를 달성하기위한 도우미 함수는 다음과 같습니다.

/**
 * Helper function to rename array keys.
 */
function _rename_arr_key($oldkey, $newkey, array &$arr) {
    if (array_key_exists($oldkey, $arr)) {
        $arr[$newkey] = $arr[$oldkey];
        unset($arr[$oldkey]);
        return TRUE;
    } else {
        return FALSE;
    }
}

@KernelM 답변을 기반으로합니다. 합니다.

용법:

_rename_arr_key('oldkey', 'newkey', $my_array);

성공적인 이름 변경시 true 를 반환 하고 , 그렇지 않으면 false를 반환 합니다 .


이렇게하면 배열의 순서가 변경됩니다 (이름이 바뀐 키의 요소는 배열의 원래 위치와 같은 위치가 아니라 배열의 끝에 있습니다). 또한 일반적으로 밑줄로 함수 이름을 시작하지 않습니다 (일반적으로 특수 내부 사용 함수를 지정하는 데 사용됨).
orrd

4

쉬운 것들 :

이 함수는 대상 $ hash를 수락하고 $ replacements는 newkey => oldkey 연관을 포함하는 해시입니다. .

이 함수는 원래 순서유지 하지만 성능 및 메모리 와 관련된 매우 큰 (10k 이상의 레코드) 배열에는 문제가 될 수 있습니다 .

function keyRename(array $hash, array $replacements) {
    $new=array();
    foreach($hash as $k=>$v)
    {
        if($ok=array_search($k,$replacements))
            $k=$ok;
        $new[$k]=$v;
    }
    return $new;    
}

이 대체 함수는 원래 순서를 잃어 버리는 비용 으로 훨씬 더 나은 성능 및 메모리 사용으로 동일한 작업을 수행합니다 (해시 테이블이므로 문제가되지 않습니다!)

function keyRename(array $hash, array $replacements) {

    foreach($hash as $k=>$v)
        if($ok=array_search($k,$replacements))
        {
          $hash[$ok]=$v;
          unset($hash[$k]);
        }

    return $hash;       
}

4

이 코드는 이전 키를 새 것으로 변경하는 데 도움이됩니다.

$i = 0;
$keys_array=array("0"=>"one","1"=>"two");

$keys = array_keys($keys_array);

for($i=0;$i<count($keys);$i++) {
    $keys_array[$keys_array[$i]]=$keys_array[$i];
    unset($keys_array[$i]);
}
print_r($keys_array);

처럼 표시

$keys_array=array("one"=>"one","two"=>"two");

3

두 솔루션의 간단한 벤치 마크 비교.

해결 방법 1 복사 및 제거 (주문 손실) https://stackoverflow.com/a/240676/1617857

for ($i =0; $i < 100000000; $i++){
    $array = ['test' => 'value'];
    $array['test2'] = $array['test'];
    unset($array['test']);
}

해결 방법 2 키 이름을 https://stackoverflow.com/a/21299719/1617857로 바꾸십시오.

for ($i =0; $i < 100000000; $i++){
    $array = ['test' => 'value'];
    $keys = array_keys( $array );
    $keys[array_search('test', $keys, true)] = 'test2';
    array_combine( $keys, $array );
}

결과 :

php solution1.php  6.33s  user 0.02s system 99% cpu 6.356  total
php solution1.php  6.37s  user 0.01s system 99% cpu 6.390  total
php solution2.php  12.14s user 0.01s system 99% cpu 12.164 total
php solution2.php  12.57s user 0.03s system 99% cpu 12.612 total

2

array_walk를 기반으로이 함수를 사용할 수 있습니다.

function mapToIDs($array, $id_field_name = 'id')
{
    $result = [];
    array_walk($array, 
        function(&$value, $key) use (&$result, $id_field_name)
        {
            $result[$value[$id_field_name]] = $value;
        }
    );
    return $result;
}

$arr = [0 => ['id' => 'one', 'fruit' => 'apple'], 1 => ['id' => 'two', 'fruit' => 'banana']];
print_r($arr);
print_r(mapToIDs($arr));

그것은 제공합니다 :

Array(
    [0] => Array(
        [id] => one
        [fruit] => apple
    )
    [1] => Array(
        [id] => two
        [fruit] => banana
    )
)

Array(
    [one] => Array(
        [id] => one
        [fruit] => apple
    )
    [two] => Array(
        [id] => two
        [fruit] => banana
    )
)

1

이것은 첫 번째 키 이름을 바꾸는 데 효과적입니다.

$a = ['catine' => 'cat', 'canine'  => 'dog'];
$tmpa['feline'] = $a['catine'];
unset($a['catine']);
$a = $tmpa + $a;

그런 다음 print_r ($ a)는 복구 된 순서대로 배열을 렌더링합니다.

Array
(
    [feline] => cat
    [canine] => dog
)

이것은 임의의 키 이름을 바꾸는 데 효과적입니다.

$a = ['canine'  => 'dog', 'catine' => 'cat', 'porcine' => 'pig']
$af = array_flip($a)
$af['cat'] = 'feline';
$a = array_flip($af)

print_r ($ a)

Array
(
    [canine] => dog
    [feline] => cat
    [porcine] => pig
)

일반화 된 기능 :

function renameKey($oldkey, $newkey, $array) {
    $val = $array[$oldkey];
    $tmp_A = array_flip($array);
    $tmp_A[$val] = $newkey;

    return array_flip($tmp_A);
}

1

여러 키를 한 번에 바꾸려면 (순서를 유지) :

/**
 * Rename keys of an array
 * @param array $array (asoc)
 * @param array $replacement_keys (indexed)
 * @return array
 */
function rename_keys($array, $replacement_keys)  {
      return array_combine($replacement_keys, array_values($array));
}

용법:

$myarr = array("a" => 22, "b" => 144, "c" => 43);
$newkeys = array("x","y","z");
print_r(rename_keys($myarr, $newkeys));
//must return: array("x" => 22, "y" => 144, "z" => 43);

1

배열의 순서를 변경하지 않고 전체 배열로 작업 할 때 배열 요소의 키를 변경하는 다른 방법이 있습니다. 단순히 배열을 새 배열로 복사하는 것입니다.

예를 들어, 색인 및 연관 키가 포함 된 혼합 된 다차원 배열을 사용하고 있었으며 순서를 어 기지 않고 정수 키를 해당 값으로 바꾸고 싶었습니다.

모든 숫자 배열 항목에 대해 키 / 값을 전환하여 이렇게했습니다. [ '0'=> 'foo']. 순서는 그대로입니다.

<?php
$arr = [
    'foo',
    'bar'=>'alfa',
    'baz'=>['a'=>'hello', 'b'=>'world'],
];

foreach($arr as $k=>$v) {
    $kk = is_numeric($k) ? $v : $k;
    $vv = is_numeric($k) ? null : $v;
    $arr2[$kk] = $vv;
}

print_r($arr2);

산출:

Array (
    [foo] => 
    [bar] => alfa
    [baz] => Array (
            [a] => hello
            [b] => world
        )
)

1

가장 좋은 방법은 참조를 사용하고 unset을 사용하지 않는 것입니다 (메모리를 청소하는 또 다른 단계를 만듭니다)

$tab = ['two' => [] ];

해결책:

$tab['newname'] = & $tab['two'];

당신은 하나의 원본과 새로운 이름을 가진 하나의 참조가 있습니다.

또는 하나의 값으로 두 개의 이름을 원하지 않으면 다른 탭을 만들고 참조 할 때마다

foreach($tab as $key=> & $value) {
    if($key=='two') { 
        $newtab["newname"] = & $tab[$key];
     } else {
        $newtab[$key] = & $tab[$key];
     }
}

반복은 키를 사용하여 모든 배열을 복제하는 것보다 좋으며 100 행 + ++ 등과 같은 긴 데이터가있는 경우 오래된 배열을 정리합니다.


0

흠, 전에 테스트하지는 않았지만이 코드가 작동한다고 생각합니다.

function replace_array_key($data) {
    $mapping = [
        'old_key_1' => 'new_key_1',
        'old_key_2' => 'new_key_2',
    ];

    $data = json_encode($data);
    foreach ($mapping as $needed => $replace) {
        $data = str_replace('"'.$needed.'":', '"'.$replace.'":', $data);
    }

    return json_decode($data, true);
}

JSON 인코딩 및 디코딩? 이것은 정말 나쁜 대답입니다.
kixorz

0

이해하기 쉬운 순서를 보존하는 것 :

function rename_array_key(array $array, $old_key, $new_key) {
  if (!array_key_exists($old_key, $array)) {
      return $array;
  }
  $new_array = [];
  foreach ($array as $key => $value) {
    $new_key = $old_key === $key
      ? $new_key
      : $key;
    $new_array[$new_key] = $value;
  }
  return $new_array;
}

0

주어진 배열의 키에 콜백을 적용하는 간단한 함수를 작성할 수 있습니다. array_map 와 유사

<?php
function array_map_keys(callable $callback, array $array) {
    return array_merge([], ...array_map(
        function ($key, $value) use ($callback) { return [$callback($key) => $value]; },
        array_keys($array),
        $array
    ));
}

$array = ['a' => 1, 'b' => 'test', 'c' => ['x' => 1, 'y' => 2]];
$newArray = array_map_keys(function($key) { return 'new' . ucfirst($key); }, $array);

echo json_encode($array); // {"a":1,"b":"test","c":{"x":1,"y":2}}
echo json_encode($newArray); // {"newA":1,"newB":"test","newC":{"x":1,"y":2}}

요점은 https://gist.github.com/vardius/650367e15abfb58bcd72ca47eff096ca#file-array_map_keys-php 입니다.


0

이 기능은 인덱스 검색과 결합하여 위치를 유지하면서 배열 키의 이름을 바꿉니다.

function renameArrKey($arr, $oldKey, $newKey){
    if(!isset($arr[$oldKey])) return $arr; // Failsafe
    $keys = array_keys($arr);
    $keys[array_search($oldKey, $keys)] = $newKey;
    $newArr = array_combine($keys, $arr);
    return $newArr;
}

용법:

$arr = renameArrKey($arr, 'old_key', 'new_key');

-1

이 기본 기능은 배열 키 교환 및 배열을 원래 순서대로 유지하는 것을 처리합니다.

public function keySwap(array $resource, array $keys)
{
    $newResource = [];

    foreach($resource as $k => $r){
        if(array_key_exists($k,$keys)){
            $newResource[$keys[$k]] = $r;
        }else{
            $newResource[$k] = $r;
        }
    }

    return $newResource;
}

그런 다음 모든 'a'키를 반복하여 'z'로 바꿀 수 있습니다 (예 : ...).

$inputs = [
  0 => ['a'=>'1','b'=>'2'],
  1 => ['a'=>'3','b'=>'4']
]

$keySwap = ['a'=>'z'];

foreach($inputs as $k=>$i){
    $inputs[$k] = $this->keySwap($i,$keySwap);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.