สตริงตัวเลขเป็นคีย์อาร์เรย์ใน PHP


105

เป็นไปได้หรือไม่ที่จะใช้สตริงตัวเลขเช่น"123"คีย์ในอาร์เรย์ PHP โดยไม่ต้องแปลงเป็นจำนวนเต็ม

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

พิมพ์

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

ฉันต้องการ

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

7
เนื่องจาก PHP พิมพ์แบบหลวม ๆ"123"== 123สำหรับเกือบทุกวัตถุประสงค์ อะไรคือเหตุผลที่คุณต้องการให้เป็นสตริงโดยเฉพาะ (และการมี int ไม่ดี)?
ircmaxell

17
เหตุผลที่อยู่ในใจของฉันเกี่ยวข้องกับฟังก์ชันอาร์เรย์เช่นarray_merge "หากอาร์เรย์อินพุตมีคีย์สตริงเหมือนกันค่าที่ตามมาของคีย์นั้นจะเขียนทับคีย์ก่อนหน้าอย่างไรก็ตามหากอาร์เรย์มีคีย์ตัวเลขค่าที่ตามมาจะไม่มี เขียนทับค่าเดิม แต่จะถูกต่อท้าย "
ficuscr

8
อีกตัวอย่างหนึ่งที่สตริงตัวเลขเป็นคีย์อาร์เรย์มีปัญหา:asort
swenedo


4
กรณีการใช้งานอื่น: การทดสอบหน่วยการเปลี่ยนข้อมูล JSON การแปลงอาร์เรย์ดังกล่าวเป็น JSON และย้อนกลับจะไม่ช่วยให้คุณยืนยันว่าทั้งสองอย่างต้นฉบับและผลลัพธ์เหมือนกันทุกประการ
เดวิด

คำตอบ:


90

ไม่; ไม่มันไม่ใช่:

จากคู่มือ :

คีย์อาจเป็นจำนวนเต็มหรือสตริงก็ได้ หากคีย์เป็นตัวแทนมาตรฐานของจำนวนเต็มก็จะตีความเช่นนั้น (เช่น "8" จะถูกตีความเป็น 8 ในขณะที่ "08" จะถูกตีความเป็น "08")

ภาคผนวก

เนื่องจากความคิดเห็นด้านล่างฉันคิดว่ามันน่าจะสนุกที่จะชี้ให้เห็นว่าลักษณะการทำงานคล้ายกันแต่ไม่เหมือนกับคีย์ออบเจ็กต์ JavaScript

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

foo['10']; // "bar"
foo[10]; // "bar"
foo[012]; // "bar"
foo['012']; // undefined!

107
PHP, IE ฝั่งเซิร์ฟเวอร์
Marek Maurizio

5
ดูเหมือนว่าจะมีวิธีจริงๆ! คุณไม่เห็นด้วยกับคำตอบนี้หรือไม่? stackoverflow.com/a/35180513/247696
Flimm

1
ยังไง! .. foo [012] return "bar"
Himanshu

2
@Himanshu: เนื่องจาก php ตีความตัวเลขที่ขึ้นต้นด้วย 0 เป็นฐานแปด ดังนั้น 012 จึงเป็นเลขฐานแปด
Yeasir Arafat Majumder

49

ใช่มันเป็นไปได้โดยการส่งstdClassวัตถุอาร์เรย์:

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

ที่ให้คุณ (สูงถึง PHP เวอร์ชัน 7.1):

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

(อัปเดต: คำตอบเดิมของฉันแสดงให้เห็นวิธีที่ซับซ้อนมากขึ้นโดยใช้json_decode()และjson_encode()ไม่จำเป็น)

หมายเหตุความคิดเห็น : น่าเสียดายที่ไม่สามารถอ้างอิงค่าได้โดยตรง: $data['12']จะส่งผลให้มีการแจ้งให้ทราบล่วงหน้า

อัปเดต :
จาก PHP 7.2 คุณสามารถใช้สตริงตัวเลขเป็นคีย์เพื่ออ้างอิงค่า:

var_dump( $data['12'] ); // int 32

2
แม้ว่าการเข้าถึงค่าโดยตรงด้วยคีย์สตริงจะไม่ทำงาน เพิ่มบรรทัดนี้ในตัวอย่างของคุณ: echo $data['12'];. มันจะให้ข้อผิดพลาด "Notice: Undefined offset: 12 in - on line 5"
LS

ใช่คุณพูดถูก. สมมติว่ามันเป็นไปได้บางครั้งในอดีต
David

1
เมื่อคุณใช้ laravel dd ($ data) มันจะผิดพลาด: P
Kamil Kiełczewski

2
ใน PHP 7.2.0RC2 ลักษณะการทำงานจะเหมือนเดิม
dev0

1
เห็นได้ชัดว่าarray_key_existsจะไม่พบในเวอร์ชันเก่าเช่นกัน
Don't Panic

12

หากคุณจำเป็นต้องใช้คีย์ตัวเลขในโครงสร้างข้อมูล php อ็อบเจกต์จะทำงาน และวัตถุจะรักษาความเป็นระเบียบคุณจึงสามารถทำซ้ำได้

$obj = new stdClass();
$key = '3';
$obj->$key = 'abc';

นี่เป็นคำแนะนำที่ดีมาก ฉันกำลังเขียนโค้ดเฟรมเวิร์กและต้องเจอกับใครบางคนที่ส่งอาร์เรย์ที่อาจมีการจัดทำดัชนี "โดยบังเอิญ": array ('this', 'that') หรือ "การเชื่อมโยง" การจัดทำดัชนี: array (123 => array ('this', 'that ')). ตอนนี้ต้องขอบคุณคุณฉันสามารถพิมพ์คำใบ้ได้) +1
Just Plain High

แต่เป็นไปได้ไหมที่จะใช้สตริงตัวเลขเช่น "123" เป็นคีย์ในอาร์เรย์ PHP โดยที่ไม่ต้องแปลงเป็นจำนวนเต็ม
Flimm

@Flimm ไม่เป็นไปไม่ได้นั่นคือเหตุผลที่ฉันเสนอทางออกของฉัน
นึ่ง

@Flimm คำตอบนั้นดูเหมือนจะขัดแย้งกับคู่มือ PHP : สตริงที่มีจำนวนเต็มที่ถูกต้องจะถูกส่งไปยังประเภทจำนวนเต็ม เช่นคีย์ "8" จะถูกเก็บไว้ภายใต้ 8 จริง ๆ ในทางกลับกัน "08" จะไม่ถูกส่งเนื่องจากไม่ใช่จำนวนเต็มทศนิยมที่ถูกต้อง แม้ว่าฉันจะไม่ได้ทดสอบคำตอบของเขา
นึ่ง

ประโยคนั้นอยู่ในส่วน "การระบุด้วยarray()ดังนั้นฉันจึงสมมติว่าในบริบทสตริงที่ระบุจำนวนเต็มที่ถูกต้องจะถูกเหวี่ยงเป็นประเภทจำนวนเต็ม แต่ปรากฎว่ามีวิธีอื่นในการสร้างอาร์เรย์ซึ่งจะไม่เกิดขึ้น เช่นในคำตอบของเดวิดที่ฉันได้ทดสอบ
Flimm

10

วิธีแก้ปัญหาของฉันคือ:

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

อักขระช่องว่าง (นำหน้า) เป็นทางออกที่ดีเพราะให้การแปลง int:

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

คุณจะเห็น 55 เป็น int


4
หรือ"0$id" => $value. เตรียม0งานไว้ล่วงหน้าด้วย
nawfal

คุณกำลังบอกว่ามันเป็นไปไม่ได้ที่จะใช้สตริงตัวเลขเช่น "123" เป็นคีย์ในอาร์เรย์ PHP โดยที่มันไม่ถูกแปลงเป็นจำนวนเต็ม?
Flimm

5

คุณสามารถพิมพ์คีย์เป็นสตริงได้ แต่สุดท้ายจะถูกแปลงเป็นจำนวนเต็มเนื่องจาก PHP พิมพ์หลวม ดูตัวคุณเอง:

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

จากคู่มือ PHP:

คีย์อาจเป็นจำนวนเต็มหรือสตริงก็ได้ หากคีย์เป็นตัวแทนมาตรฐานของจำนวนเต็มก็จะตีความเช่นนี้ (เช่น "8" จะถูกตีความเป็น 8 ในขณะที่ "08" จะถูกตีความเป็น "08") การลอยตัวในคีย์จะถูกตัดทอนเป็นจำนวนเต็ม ประเภทอาร์เรย์ที่จัดทำดัชนีและเชื่อมโยงเป็นประเภทเดียวกันใน PHP ซึ่งสามารถมีดัชนีเลขจำนวนเต็มและสตริงได้


1
การแปลงไม่ได้เกิดจากการพิมพ์หลวม php กำหนดว่าสตริงมีลักษณะเป็นตัวเลขหรือไม่จากนั้นจึงแปลง
Ja͢ck

1
คุณกำลังบอกว่ามันเป็นไปไม่ได้เหรอ? คำตอบนี้แสดงให้เห็นว่ามีวิธีใช้สตริงที่ดูเหมือนจำนวนเต็มเป็นคีย์ในอาร์เรย์
Flimm

IMHO ปัญหาคือล่าม PHP เป็นไปไม่ได้ที่จะจินตนาการว่ามีภาษาที่ผสมสตริงและจำนวนเต็มเป็นคีย์อาร์เรย์ ทางออกที่ดีที่สุด? ตามที่เสนอโดย Undolog stackoverflow.com/a/15413637/1977778ทางออกที่ดีที่สุดคือใช้ช่องว่างต่อท้าย ... น่าเศร้า
sentenza

@sentenza: เป็นไปได้ที่จะจินตนาการได้โดยเฉพาะอย่างยิ่งเนื่องจาก PHP อนุญาตให้มีการผสมผสานระหว่างสตริงและจำนวนเต็มเป็นคีย์ของอาร์เรย์:[42 => 'answer', 'snafu' => 'fubar']
LS

@LS ครับ ฉันรู้ว่า PHP ช่วยให้คุณทำได้ แต่ถ้าคุณพิจารณาคีย์ภายในระบบประเภททั่วไปสมมุติจะไม่ตรงกับประเภทผสมใด ๆที่รวบรวมสตริงและตัวเลขในเวลาเดียวกัน การพิมพ์แบบหลวม ๆ ที่ใช้กับคีย์ของอาร์เรย์ที่เชื่อมโยงเป็นเพียงข้อผิดพลาดที่เกิดขึ้นได้ง่าย
sentenza

1

ฉันมีปัญหานี้ในการพยายามผสานอาร์เรย์ซึ่งมีทั้งสตริงและคีย์จำนวนเต็ม สิ่งสำคัญคือจำนวนเต็มจะถูกจัดการเป็นสตริงเนื่องจากเป็นชื่อสำหรับช่องป้อนข้อมูล (เช่นขนาดรองเท้าเป็นต้น)

เมื่อฉันใช้$data = array_merge($data, $extra);PHP จะ 'สั่งซื้อใหม่' คีย์ ในความพยายามทำการสั่งซื้อคีย์จำนวนเต็ม (ฉันพยายามด้วย6- '6'- "6"แม้(string)"6"เป็นคีย์) จะถูกเปลี่ยนชื่อจาก 0 เป็นn... หากคุณคิดเกี่ยวกับมันในกรณีส่วนใหญ่นี่จะเป็นพฤติกรรมที่ต้องการ

คุณสามารถแก้ไขปัญหานี้ได้โดยใช้$data = $data + $extra;แทน ตรงไปตรงมาสวย แต่ตอนแรกไม่ได้คิด ^^.


ปัญหาเดียวกันทำให้ฉันมาที่หน้านี้ แต่ฉันต้องบอกว่านี่ไม่ใช่คำตอบสำหรับคำถามของ OP
Flimm

@ ฟลิม์ทรู. แต่การค้นหาคำตอบทำให้ฉันมาที่หน้านี้ ฉันคิดว่าวิธีแก้ปัญหาของฉันอาจช่วยให้ Googler คนอื่น ๆ :)
Brainfeeder

1

สตริงที่มีจำนวนเต็มที่ถูกต้องจะถูกเหวี่ยงเป็นประเภทจำนวนเต็ม เช่นคีย์ "8" จะถูกเก็บไว้ภายใต้ 8 จริง ๆ ในทางกลับกัน "08" จะไม่ถูกส่งเนื่องจากไม่ใช่จำนวนเต็มทศนิยมที่ถูกต้อง

ไม่ถูกต้อง

ฉันมีฟังก์ชั่นการหล่อที่จัดการตามลำดับกับการหล่ออาร์เรย์ที่เชื่อมโยง

$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
}

1

วิธีแก้ปัญหาชั่วคราวคุณสามารถเข้ารหัสอาร์เรย์ PHP เป็นวัตถุ json โดยใช้ตัวเลือก JSON_FORCE_OBJECT

เช่นตัวอย่างนี้:

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

จะส่งผลให้:

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

0

ฉันพบปัญหานี้ในอาร์เรย์ที่มีทั้ง '0' และ '' เป็นคีย์ หมายความว่าฉันไม่สามารถตรวจสอบคีย์อาร์เรย์ของฉันด้วย == หรือ ===

$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";
    }
}

วิธีแก้ปัญหาคือการส่งคีย์อาร์เรย์กลับไปที่สตริงก่อนใช้งาน

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";
    }
}

1
นี่ไม่ใช่คำตอบสำหรับคำถามจริงๆ
Flimm

0

เกี่ยวกับโซลูชัน @david โปรดทราบว่าเมื่อคุณพยายามเข้าถึงค่าสตริงในอาร์เรย์ที่เชื่อมโยงตัวเลขจะไม่ทำงาน ฉันเดาว่าพวกมันถูกเหวี่ยงเป็นจำนวนเต็มเบื้องหลัง (เมื่อเข้าถึงอาร์เรย์) และไม่พบค่า การเข้าถึงค่าเป็นจำนวนเต็มจะใช้ไม่ได้เช่นกัน แต่คุณสามารถใช้ array_shift () เพื่อรับค่าหรือวนซ้ำอาร์เรย์ได้

$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)

php เวอร์ชั่นไหน ฉันพยายามว่าตัวอย่างของคุณและที่สำคัญ"0"กลายเป็น0ด้วย 7.2.10php
J.BizMai

-1

ฉันมีปัญหานี้ขณะพยายามจัดเรียงอาร์เรย์ซึ่งฉันต้องการคีย์การจัดเรียงเป็น hex sha1 เมื่อค่า sha1 ที่เป็นผลลัพธ์ไม่มีตัวอักษร PHP จะเปลี่ยนคีย์เป็นจำนวนเต็ม แต่ฉันต้องการเรียงอาร์เรย์ตามลำดับสัมพัทธ์ของสตริง ดังนั้นฉันจึงต้องหาวิธีบังคับให้คีย์เป็นสตริงโดยไม่ต้องเปลี่ยนลำดับการจัดเรียง

ดูที่แผนภูมิ ASCII ( https://en.wikipedia.org/wiki/ASCII ) เครื่องหมายอัศเจรีย์จะเรียงลำดับเช่นเดียวกับช่องว่างและต่ำกว่าตัวเลขและตัวอักษรทั้งหมด

ดังนั้นฉันจึงใส่เครื่องหมายอัศเจรีย์ต่อท้ายสตริงคีย์

for(...) {

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

ksort($database);
$row = reset($database);
$topsha = $row[0];

คุณกำลังบอกว่าเป็นไปไม่ได้ที่จะใช้สตริงตัวเลขเช่น "123" เป็นคีย์ในอาร์เรย์ PHP โดยที่ไม่ต้องแปลงเป็นจำนวนเต็ม?
Flimm

ไม่ - จะถือว่าเฉพาะคีย์ที่เป็นตัวเลขทั้งหมดเป็นจำนวนเต็มเมื่อจัดเรียงอาร์เรย์โดยใช้ ksort () - จะไม่ถูกแปลงเป็นจำนวนเต็ม - เพียงแค่เปรียบเทียบเป็นค่าเดียวในระหว่างการเรียงลำดับ
drchuck
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.