String numerik sebagai kunci array di PHP

104

Apakah mungkin menggunakan string numerik seperti "123"sebagai kunci dalam array PHP, tanpa diubah menjadi integer?

$blah = array('123' => 1);
var_dump($blah);

cetakan

array(1) {
  [123]=>
  int(1)
}

saya ingin

array(1) {
  ["123"]=>
  int(1)
}
Dogbert
sumber
7
Karena PHP diketik secara longgar, "123"== 123untuk hampir semua tujuan. Apa alasan Anda menginginkannya secara khusus sebagai string (dan memiliki int itu buruk)?
ircmaxell
17
Alasan yang terlintas di benak saya berkaitan dengan fungsi array seperti array_merge "Jika array input memiliki kunci string yang sama, maka nilai kunci itu akan menimpa yang sebelumnya. Namun, jika array berisi kunci numerik , nilai yang kemudian tidak akan menimpa nilai asli, tetapi akan ditambahkan. "
ficuscr
8
Contoh lain di mana string numerik sebagai kunci array bermasalah:asort
swenedo
4
Kasus penggunaan lain: transisi data JSON pengujian unit. Mengonversi larik seperti itu ke JSON dan kembali tidak akan membiarkan Anda menegaskan bahwa keduanya, yang asli dan hasilnya persis sama.
David

Jawaban:

90

Tidak; tidak, bukan:

Dari manual :

Kunci bisa berupa integer atau string. Jika kunci adalah representasi standar dari sebuah integer, itu akan diinterpretasikan seperti itu (misalnya "8" akan diartikan sebagai 8, sedangkan "08" akan diartikan sebagai "08").

Tambahan

Karena komentar di bawah ini, saya pikir akan menyenangkan untuk menunjukkan bahwa perilakunya mirip tetapi tidak identik dengan kunci objek JavaScript.

foo = { '10' : 'bar' };

foo['10']; // "bar"
foo[10]; // "bar"
foo[012]; // "bar"
foo['012']; // undefined!
Hamish
sumber
107
PHP, IE sisi server.
Marek Maurizio
5
Sepertinya ada jalan, sebenarnya! Apakah Anda tidak setuju dengan jawaban ini? stackoverflow.com/a/35180513/247696
Flimm
1
Bagaimana?! .. foo [012] mengembalikan "bar"
Himanshu
2
@Himanshu: karena php mengartikan angka yang dimulai dengan 0 sebagai oktal. jadi 012 adalah 10 oktal.
Yeasir Arafat Majumder
49

Ya, dimungkinkan dengan melakukan array-casting pada stdClassobjek:

$data =  new stdClass;
$data->{"12"} = 37;
$data = (array) $data;
var_dump( $data );

Itu memberi Anda (hingga PHP versi 7.1):

array(1) {
  ["12"]=>
  int(37)
}

(Pembaruan: Jawaban asli saya menunjukkan cara yang lebih rumit dengan menggunakan json_decode()dan json_encode()mana yang tidak perlu.)

Perhatikan komentarnya : Sayangnya tidak mungkin untuk mereferensikan nilai secara langsung: $data['12']akan menghasilkan pemberitahuan.

Pembaruan :
Dari PHP 7.2 di atasnya juga dimungkinkan untuk menggunakan string numerik sebagai kunci untuk merujuk nilai:

var_dump( $data['12'] ); // int 32
David
sumber
2
Akses langsung dari nilai dengan kunci string tidak berfungsi. Tambahkan baris ini ke contoh Anda: echo $data['12'];. Ini akan memberikan kesalahan, "Pemberitahuan: Offset yang tidak ditentukan: 12 in - on line 5".
LS
1
ketika U menggunakan laravel dd ($ data) itu akan macet: P
Kamil Kiełczewski
2
Dalam PHP 7.2.0RC2 perilakunya sama seperti sebelumnya.
dev0
1
Rupanya array_key_existstidak akan menemukannya di versi lama juga.
Jangan Panik
1
tidak bekerja di php 7.4
melati
12

Jika Anda perlu menggunakan kunci numerik dalam struktur data php, sebuah objek akan berfungsi. Dan objek menjaga keteraturan, sehingga Anda dapat mengulang.

$obj = new stdClass();
$key = '3';
$obj->$key = 'abc';
ditenagai uap
sumber
Ini adalah saran yang sangat bagus. Saya menulis kode kerangka kerja dan berhadapan dengan seseorang yang melewati larik yang dapat memiliki pengindeksan "tidak disengaja": array ('this', 'that') atau "asosiatif" pengindeksan: array (123 => array ('this', 'that ')). Sekarang, terima kasih kepada Anda, saya bisa mengetik;) +1
Just Plain High
Tapi apakah mungkin menggunakan string numerik seperti "123" sebagai kunci dalam array PHP, tanpa diubah menjadi integer?
Flimm
@Flimm no itu tidak mungkin, itulah sebabnya saya menawarkan solusi saya.
steampowered
@Flimm jawaban itu tampaknya bertentangan dengan manual PHP : String yang berisi bilangan bulat yang valid akan dimasukkan ke jenis bilangan bulat. Misalnya kunci "8" sebenarnya akan disimpan di bawah 8. Di sisi lain, "08" tidak akan dilemparkan, karena ini bukan bilangan bulat desimal yang valid. , meskipun saya belum menguji jawabannya.
steampowered
Kalimat itu ada di bawah bagian "Menentukan dengan array(), jadi saya berasumsi bahwa dalam konteks itu, string yang menentukan bilangan bulat valid akan dimasukkan ke jenis bilangan bulat. Tapi ternyata ada cara lain untuk membuat larik, di mana itu tidak terjadi, seperti dalam jawaban David, yang telah saya uji.
Flimm
10

Solusi saya adalah:

$id = 55;
$array = array(
  " $id" => $value
);

Ruang char (prepend) adalah solusi yang baik karena pertahankan konversi int:

foreach( $array as $key => $value ) {
  echo $key;
}

Anda akan melihat 55 sebagai int.

Undolog
sumber
4
Atau "0$id" => $value. Mempersiapkan 0pekerjaan juga.
nawfal
Jadi Anda mengatakan bahwa tidak mungkin menggunakan string numerik seperti "123" sebagai kunci dalam array PHP, tanpa diubah menjadi integer?
Flimm
5

Anda dapat mengetikkan kunci ke string tetapi pada akhirnya akan dikonversi menjadi bilangan bulat karena pengetikan longgar PHP. Lihat diri mu sendiri:

$x=array((string)123=>'abc');
var_dump($x);
$x[123]='def';
var_dump($x);

Dari manual PHP:

Kunci bisa berupa integer atau string. Jika kunci adalah representasi standar dari sebuah bilangan bulat, itu akan diinterpretasikan seperti itu (misalnya "8" akan diartikan sebagai 8, sedangkan "08" akan diartikan sebagai "08"). Kunci mengambang di potong menjadi bilangan bulat. Jenis array yang diindeks dan asosiatif adalah jenis yang sama di PHP, yang dapat berisi indeks integer dan string.

bcosca.dll
sumber
1
Konversi ini bukan karena pengetikan yang longgar; php menentukan apakah string terlihat numerik dan kemudian mengubahnya.
Ja͢ck
1
Jadi, apakah Anda mengatakan itu tidak mungkin? Jawaban ini menunjukkan bahwa ada cara untuk menggunakan string yang terlihat seperti integer sebagai kunci dalam array.
Flimm
IMHO masalahnya adalah interpreter PHP. Bahkan tidak mungkin membayangkan memiliki bahasa yang mencampur string dan integer sebagai kunci array. Solusi terbaik? Seperti yang diusulkan oleh Undolog stackoverflow.com/a/15413637/1977778 , solusi terbaik adalah menggunakan ruang tambahan ... Sayangnya.
sentenza
@sentenza: Ini adalah mungkin untuk membayangkan, terutama karena PHP memungkinkan campuran string dan integer sebagai kunci dari sebuah array:[42 => 'answer', 'snafu' => 'fubar']
LS
@LYa. Saya tahu bahwa PHP memungkinkan Anda untuk melakukannya, tetapi jika Anda mempertimbangkan kunci dalam sistem tipe generik hipotetis, itu tidak akan cocok dengan tipe campuran yang mencakup string dan angka pada saat yang bersamaan. The mengetik longgar diterapkan pada kunci array asosiatif hanya kesalahan rawan.
sentenza
1

Saya mengalami masalah ini mencoba menggabungkan array yang memiliki kunci string dan integer. Penting bahwa bilangan bulat juga akan ditangani sebagai string karena ini adalah nama untuk bidang masukan (seperti dalam ukuran sepatu dll, ..)

Ketika saya menggunakan $data = array_merge($data, $extra);PHP akan 'memesan ulang' kuncinya. Dalam upaya melakukan pengurutan, kunci integer (saya coba dengan 6- '6'- "6"bahkan (string)"6"sebagai kunci) diganti namanya dari 0 menjadi n... Jika Anda memikirkannya, dalam banyak kasus ini akan menjadi perilaku yang diinginkan.

Anda dapat mengatasinya dengan menggunakan $data = $data + $extra;. Cukup lurus ke depan, tapi saya tidak memikirkannya pada awalnya ^^.

Pemberi makan otak
sumber
Masalah yang persis sama membawa saya ke halaman ini, tetapi saya harus mengatakan bahwa ini bukan jawaban untuk pertanyaan OP.
Flimm
@Tokopedia Tetapi mencari jawaban membawa saya ke halaman ini. Saya pikir solusi saya dapat membantu untuk Googler lainnya :)
Brainfeeder
1

String yang berisi bilangan bulat yang valid akan dimasukkan ke jenis bilangan bulat. Misalnya, kunci "8" sebenarnya akan disimpan di bawah 8. Di sisi lain "08" tidak akan dilemparkan, karena ini bukan bilangan bulat desimal yang valid.

SALAH

Saya memiliki fungsi casting yang menangani casting array berurutan ke asosiatif,

$array_assoc = cast($arr,'array_assoc');

$array_sequential = cast($arr,'array_sequential');

$obj = cast($arr,'object');

$json = cast($arr,'json');



function cast($var, $type){

    $orig_type = gettype($var);

    if($orig_type == 'string'){

        if($type == 'object'){
            $temp = json_decode($var);
        } else if($type == 'array'){
            $temp = json_decode($var, true);
        }
        if(isset($temp) && json_last_error() == JSON_ERROR_NONE){
            return $temp;
        }
    }
    if(@settype($var, $type)){
        return $var;
    }
    switch( $orig_type ) {

        case 'array' :

            if($type == 'array_assoc'){

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

            } else if($type == 'array_sequential'){

                return array_values($var);

            } else if($type == 'json'){

                return json_encode($var);
            }
        break;
    }
    return null; // or trigger_error
}
TarranJones
sumber
tidak bekerja di php 7.4
melati
1

Sebagai solusinya, Anda dapat mengenkode array PHP ke dalam objek json, dengan opsi JSON_FORCE_OBJECT.

yaitu, contoh ini:

     $a = array('foo','bar','baz');
     echo "RESULT: ", json_encode($a, JSON_FORCE_OBJECT);

akan menghasilkan:

     RESULT: {"0" : "foo", "1": "bar", "2" : "baz"}
GigiManco
sumber
0

Saya mengalami masalah ini pada array dengan '0' dan '' sebagai kuncinya. Itu berarti saya tidak bisa memeriksa kunci array saya dengan == atau ===.

$array=array(''=>'empty', '0'=>'zero', '1'=>'one');
echo "Test 1\n";
foreach ($array as $key=>$value) {
    if ($key == '') { // Error - wrongly finds '0' as well
        echo "$value\n";
    }
}
echo "Test 2\n";
foreach ($array as $key=>$value) {
    if ($key === '0') { // Error - doesn't find '0'
        echo "$value\n";
    }
}

Solusinya adalah dengan mengembalikan kunci array ke string sebelum digunakan.

echo "Test 3\n";
foreach ($array as $key=>$value) {
    if ((string)$key == '') { // Cast back to string - fixes problem
        echo "$value\n";
    }
}
echo "Test 4\n";
foreach ($array as $key=>$value) {
    if ((string)$key === '0') { // Cast back to string - fixes problem
        echo "$value\n";
    }
}
fisharebest
sumber
1
Ini sebenarnya bukan jawaban untuk pertanyaan itu.
Flimm
0

Mengenai solusi @david, harap diperhatikan bahwa saat Anda mencoba mengakses nilai string dalam array asosiatif, angka tidak akan berfungsi. Dugaan saya adalah bahwa mereka dicor ke bilangan bulat di belakang layar (saat mengakses array) dan tidak ada nilai yang ditemukan. Mengakses nilai sebagai integer juga tidak akan berfungsi. Tapi Anda bisa menggunakan array_shift () untuk mendapatkan nilai atau mengulang array.

$data = new stdClass;
$data->{"0"} = "Zero";
$data->{"1"} = "One";
$data->{"A"} = "A";
$data->{"B"} = "B";

$data = (array)$data;

var_dump($data);
/*
Note the key "0" is correctly saved as a string:
array(3) {
  ["0"]=>
  string(4) "Zero"
  ["A"]=>
  string(1) "A"
  ["B"]=>
  string(1) "B"
}
*/

//Now let's access the associative array via the values 
//given from var_dump() above:
var_dump($data["0"]); // NULL -> Expected string(1) "0"
var_dump($data[0]); // NULL (as expected)
var_dump($data["1"]); // NULL -> Expected string(1) "1"
var_dump($data[1]); // NULL (as expected)
var_dump($data["A"]); // string(1) "A" (as expected)
var_dump($data["B"]); // string(1) "B" (as expected)
Nico Schefer
sumber
Versi php yang mana? Saya mencoba dengan tepat contoh Anda dan kuncinya "0"menjadi 0dengan php 7.2.10.
J.BizMai
-1

Saya mengalami masalah ini ketika mencoba mengurutkan array di mana saya membutuhkan kunci sortir menjadi hex sha1. Ketika nilai sha1 yang dihasilkan tidak memiliki huruf, PHP mengubah kunci menjadi integer. Tapi saya perlu mengurutkan array pada urutan relatif string. Jadi saya perlu menemukan cara untuk memaksa kunci menjadi string tanpa mengubah urutan pengurutan.

Melihat bagan ASCII ( https://en.wikipedia.org/wiki/ASCII ) tanda seru diurutkan hampir sama dengan spasi dan tentunya lebih rendah dari semua angka dan huruf.

Jadi saya menambahkan tanda seru di akhir string kunci.

for(...) {

    $database[$sha.'!'] = array($sha,$name,$age);
}

ksort($database);
$row = reset($database);
$topsha = $row[0];
drchuck
sumber
Jadi, apakah Anda mengatakan bahwa tidak mungkin menggunakan string numerik seperti "123" sebagai kunci dalam array PHP, tanpa diubah menjadi integer?
Flimm
Tidak - ini hanya memperlakukan kunci yang berupa semua bilangan sebagai bilangan bulat saat mengurutkan larik menggunakan ksort () - ia tidak pernah diubah menjadi bilangan bulat - hanya dibandingkan sebagai satu selama penyortiran.
drchuck