development

PHP가 배열 키에 문자열을 사용하도록하려면 어떻게해야합니까?

big-blog 2021. 1. 8. 22:48
반응형

PHP가 배열 키에 문자열을 사용하도록하려면 어떻게해야합니까?


예를 들어 유형 배열의 이름을 지정하는 데 ID를 사용하는 오래된 앱을 보았습니다.

array(1) {
  [280]=>
  string(3) "abc"
}

이제 이것들을 재정렬해야합니다 var_dump(). 그러면 키가 정수인 동안에는 이런 일이 일어나지 않는 것처럼 보일 것입니다.

a모든 인덱스에을 추가하면 var_dump()키 주위에 큰 따옴표가 표시됩니다. 이제 표시하려는 추측은 이제 문자열입니다.

array(1) {
  ["280a"]=>
  string(3) "abc"
}

이렇게하면 더 많은 코드를 건드리지 않고도 쉽게 재정렬 할 수 있습니다.

이것은 작동하지 않습니다 .

$newArray = array();
foreach($array as $key => $value) {
   $newArray[(string) $key] = $value;
}

A는 var_dump()여전히 그것들을 정수 배열 인덱스로 보여줍니다.

키를 문자열로 강제하는 방법이 있습니까? 배열을 손상시키지 않고 다시 정렬 할 수 있습니까?


편집 :

정수라면 키를 변경하지 않고 재정렬 할 수 없다고 가정했습니다 (이 예에서 중요합니다). 그러나 문자열 인 경우 인덱스가 특별한 의미를 갖도록 해석되어서는 안되므로 원하는 방식으로 재정렬 할 수 있습니다. 어쨌든, 내가 어떻게했는지에 대한 내 질문 업데이트를 참조하십시오 (다른 경로로 내려갔습니다).

실제로 숫자 순서 일 필요는 없습니다 ...

array(208=>'a', 0=> 'b', 99=>'c');

수동으로 할당하면 완벽하게 유효합니다. 내가 동의하지만 정수 키가 숫자가 아닌 순서로 있다면 그것이 아닌 것이 분명하다고 생각할지라도 누군가에 의해 순차적 의미를 갖는 것으로 잘못 해석 될 수 있습니다. 업데이트함에 따라 코드를 변경할 여지가 있었기 때문에 더 나은 접근 방식이라고 생각합니다.


아마도 가장 효율적인 방법은 아니지만 파이처럼 쉽습니다.

$keys = array_keys($data);

$values = array_values($data);
$stringKeys = array_map('strval', $keys);

$data = array_combine($stringKeys, $values);

//sort your data

당신은 할 수 없습니다!

유효한 정수를 포함하는 문자열은 정수 유형으로 캐스트됩니다. 예를 들어 키 "8"은 실제로 8 아래에 저장됩니다. 반면에 "08"은 유효한 십진 정수가 아니기 때문에 캐스트되지 않습니다.

편집하다:

실제로 할 수 있습니다! 순차 배열을 연관 배열로 캐스트

$obj = new stdClass;
foreach($array as $key => $value){
    $obj->{$key} = $value;
}
$array = (array) $obj;

대부분의 경우 다음은 사실입니다.

유효한 정수를 포함하는 문자열은 정수 유형으로 캐스트됩니다. 예를 들어 키 "8"은 실제로 8 아래에 저장됩니다. 반면에 "08"은 유효한 십진 정수가 아니기 때문에 캐스트되지 않습니다.

PHP 문서의이 예

 <?php
    $array = array(
        1    => "a",
        "1"  => "b",
        1.5  => "c",
        true => "d",
    );
    var_dump($array);
?>

위의 예는 다음을 출력합니다.

array(1) {
  [1]=> string(1) "d"
}

따라서 번호가 매겨진 키로 배열을 생성하더라도 정수로 다시 형변환됩니다.

불행히도 나는 최근까지 이것을 알지 못했지만 실패한 시도를 공유 할 것입니다.

실패한 시도

$arr = array_​change_​key_​case($arr); // worth a try. 

배열의 모든 키가 소문자 또는 대문자 인 배열을 반환합니다. 번호가 매겨진 인덱스는 그대로 유지됩니다 .

다음 시도는 array_combine이전 값에 새 (문자열) 키 를 사용하여 새 배열을 만드는 것이 었습니다 .

$keys배열에 문자열 유형의 숫자 ​​값을 포함 하는 여러 가지 방법을 시도했습니다 .

range("A", "Z" ) 알파벳으로 작동하므로 숫자 문자열로 시도해 보겠습니다.

$keys = range("0", (string) count($arr) ); // integers

이로 인해 키로 가득 찬 배열이 생성되었지만 모두 int 유형이었습니다.

다음은 문자열 유형의 값으로 배열을 만드는 성공적인 시도입니다.

$keys = explode(',', implode(",", array_keys($arr))); // values strings

$keys = array_map('strval', array_keys($arr)); // values strings

이제 두 가지를 결합합니다.

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

이것은 숫자 문자열이 정수로 캐스트된다는 것을 발견했을 때입니다.

$arr = array_combine( $keys, $arr); // int strings
//assert($arr === array_values($arr)) // true. 

문자열의 열쇠를 변경하고 자신의 리터럴 값을 유지하는 유일한 방법은 소수점와 접미사 그것으로 키 접두사하는 것 "00","01","02"또는 "0.","1.","2.".

그렇게 할 수 있습니다.

$keys = explode(',', implode(".,", array_keys($arr)) . '.'); // added decimal point 
$arr = array_combine($keys, $arr);

물론 이것은 이와 같은 배열 요소를 대상으로해야하기 때문에 이상적이지 않습니다.

$arr["280."]   

I've created a little function which will target the correct array element even if you only enter the integer and not the new string.

function array_value($array, $key){

    if(array_key_exists($key, $array)){
        return $array[ $key ];
    }
    if(is_numeric($key) && array_key_exists('.' . $key, $array)){
        return $array[ '.' . $key ];
    } 
    return null;
}

Usage

echo array_value($array, "208"); // "abc"

Edit:

ACTUALLY YOU CAN!! Cast sequential array to associative array

All that for nothing


Use an object instead of an array $object = (object)$array;


You can append the null character "\0" to the end of the array key. This makes it so PHP can't interpret the string as an integer. All of the array functions (like array_merge()) work on it. Also not even var_dump() will show anything extra after the string of integers.

Example:

$numbers1 = array();
$numbers2 = array();
$numbers = array();

$pool1 = array(111, 222, 333, 444);
$pool2 = array(555, 666, 777, 888);

foreach($pool1 as $p1)
{
    $numbers1[$p1 . "\0"] = $p1;
}
foreach($pool2 as $p2)
{
    $numbers2[$p2 . "\0"] = $p2;
}

$numbers = array_merge($numbers1, $numbers2);

var_dump($numbers);

The resulting output will be:

array(8) {
    ["111"] => string(3) "111"
    ["222"] => string(3) "222"
    ["333"] => string(3) "333"
    ["444"] => string(3) "444"
    ["555"] => string(3) "555"
    ["666"] => string(3) "666"
    ["777"] => string(3) "777"
    ["888"] => string(3) "888"
}

Without the . "\0" part the resulting array would be:

array(8) {
    [0] => string(3) "111"
    [1] => string(3) "222"
    [2] => string(3) "333"
    [3] => string(3) "444"
    [4] => string(3) "555"
    [5] => string(3) "666"
    [6] => string(3) "777"
    [7] => string(3) "888"
}

Also ksort() will also ignore the null character meaning $numbers[111] and $numbers["111\0"] will both have the same weight in the sorting algorithm.

The only downside to this method is that to access, for example $numbers["444"], you would actually have to access it via $numbers["444\0"] and since not even var_dump() will show you there's a null character at the end, there's no clue as to why you get "Undefined offset". So only use this hack if iterating via a foreach() or whoever ends up maintaining your code will hate you.


I was able to get this to work by adding '.0' onto the end of each key, as such:

$options = [];
for ($i = 1; $i <= 4; $i++) {
    $options[$i.'.0'] = $i;
}

Will return:

array("1.0" => 1, "2.0" => 2, "3.0" => 3, "4.0" => 4)

It may not be completely optimal but it does allow you to sort the array and extract (an equivalent of) the original key without having to truncate anything.


Edit: This should work

foreach($array as $key => $value) { 
    $newkey = sprintf('%s',$key);
    $newArray["'$newkey'"] = $value; 
} 

Only one commenter got this right, and the accepted answer is bad. asort(), uasort(), and arsort() are built-ins that sort arrays whilst maintaining the key associations, and they've existed since version 4. RTFM, people.

Don't escape/corrupt your data by messing with keys. You can't stop PHP from using integer keys, so don't try. It only happens when the integer representation is exactly the same as the string, so you just cast them as such when reading the keys & values from the array, i.e. (string) $key. You can do all the sort operations you need using the aforementioned functions.

ReferenceURL : https://stackoverflow.com/questions/3445953/how-can-i-force-php-to-use-strings-for-array-keys

반응형