ตรวจสอบว่าอาร์เรย์มีหลายมิติหรือไม่?


137
  1. วิธีที่มีประสิทธิภาพมากที่สุดในการตรวจสอบว่าอาร์เรย์เป็นอาร์เรย์แบบแบนของค่าดั้งเดิมหรือเป็นอาร์เรย์หลายมิติได้อย่างไร
  2. มีวิธีการทำเช่นนี้โดยไม่วนลูปผ่านอาร์เรย์และทำงานis_array()ในแต่ละองค์ประกอบหรือไม่

9
เป็นมูลค่าชี้ให้เห็นว่า PHP ไม่ได้มีอาร์เรย์หลายมิติที่แท้จริง - เพียงค่าเชื่อมโยงอาร์เรย์ที่เรียบง่าย ดังนั้นคำถามของคุณถามจริง ๆ ว่า "มีค่าที่ไม่เกลาในอาร์เรย์ของฉัน" หรือไม่?
gahooa

21
จริงๆแล้ว ... ฉันไม่คิดว่ามันคุ้มค่าที่จะชี้ให้เห็น
Joe

คำตอบ:


135

คำตอบสั้น ๆ คือคุณไม่สามารถทำได้โดยไม่วนซ้ำอย่างน้อยถ้าหาก 'มิติที่สอง' สามารถอยู่ที่ใดก็ได้ ถ้ามันจะต้องอยู่ในรายการแรกคุณจะทำ

is_array($arr[0]);

แต่วิธีทั่วไปที่มีประสิทธิภาพที่สุดที่ฉันสามารถหาได้คือการใช้ foreach loop บนอาเรย์, shortcircuiting ทุกครั้งที่พบการตี

$ more multi.php
<?php

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

function is_multi($a) {
    $rv = array_filter($a,'is_array');
    if(count($rv)>0) return true;
    return false;
}

function is_multi2($a) {
    foreach ($a as $v) {
        if (is_array($v)) return true;
    }
    return false;
}

function is_multi3($a) {
    $c = count($a);
    for ($i=0;$i<$c;$i++) {
        if (is_array($a[$i])) return true;
    }
    return false;
}
$iters = 500000;
$time = microtime(true);
for ($i = 0; $i < $iters; $i++) {
    is_multi($a);
    is_multi($b);
    is_multi($c);
}
$end = microtime(true);
echo "is_multi  took ".($end-$time)." seconds in $iters times\n";

$time = microtime(true);
for ($i = 0; $i < $iters; $i++) {
    is_multi2($a);
    is_multi2($b);
    is_multi2($c);
}
$end = microtime(true);
echo "is_multi2 took ".($end-$time)." seconds in $iters times\n";
$time = microtime(true);
for ($i = 0; $i < $iters; $i++) {
    is_multi3($a);
    is_multi3($b);
    is_multi3($c);
}
$end = microtime(true);
echo "is_multi3 took ".($end-$time)." seconds in $iters times\n";
?>

$ php multi.php
is_multi  took 7.53565130424 seconds in 500000 times
is_multi2 took 4.56964588165 seconds in 500000 times
is_multi3 took 9.01706600189 seconds in 500000 times

การวนซ้ำโดยนัย แต่เราไม่สามารถลัดวงจรทันทีที่พบการแข่งขัน ...

$ more multi.php
<?php

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

function is_multi($a) {
    $rv = array_filter($a,'is_array');
    if(count($rv)>0) return true;
    return false;
}

var_dump(is_multi($a));
var_dump(is_multi($b));
?>

$ php multi.php
bool(true)
bool(false)

3
ดีด้วยข้อแม้ที่ฉันเชื่อว่าบรรทัดการกรองของคุณควรมี array_map ("is_array", $ a) โดยไม่ใช้ is_array เป็น bareword
Matthew Scharley

ดีจับที่เร่ง is_multi แต่ก็ยังพอที่จะไม่ดีในการแข่งขัน foreach
Vinko Vrsalovic

2
เป็นที่น่าสังเกตว่า multi_3 จะทำงานในอาร์เรย์ที่ไม่มีการเชื่อมโยงแบบไม่มีศูนย์โดยไม่มีช่องว่างในดัชนีหมายความว่าจะไม่สามารถระบุตัวอย่างเหล่านี้เป็นหลายมิติได้อย่างถูกต้อง
Cragmonkey

ในฟังก์ชั่นis_multi()เพิ่มประสิทธิภาพรหัสโดยการทำreturn count($rv)>0
Xorifelse

is_array (array_values ​​($ arr) [0]) เป็นวิธีแก้ปัญหาสำหรับคีย์ที่กำหนดเอง
Vitor Rodrigues

191

ใช้จำนวน () สองครั้ง หนึ่งครั้งในโหมดเริ่มต้นและหนึ่งครั้งในโหมดเรียกซ้ำ ถ้าค่าตรงกันอาร์เรย์ไม่ใช่หลายมิติเนื่องจากอาร์เรย์หลายมิติจะมีจำนวนการเรียกซ้ำที่สูงกว่า

if (count($array) == count($array, COUNT_RECURSIVE)) 
{
  echo 'array is not multidimensional';
}
else
{
  echo 'array is multidimensional';
}

ตัวเลือกนี้modeมีการเพิ่มค่าที่สองใน PHP 4.2.0 จากเอกสาร PHP :

หากพารามิเตอร์โหมดตัวเลือกถูกตั้งค่าเป็น COUNT_RECURSIVE (หรือ 1) การนับ () จะนับอาร์เรย์ซ้ำ สิ่งนี้มีประโยชน์อย่างยิ่งสำหรับการนับองค์ประกอบทั้งหมดของอาร์เรย์หลายมิติ count () ตรวจไม่พบการเรียกซ้ำไม่สิ้นสุด

array(array())อย่างไรก็ตามวิธีการนี้ไม่ได้ตรวจสอบ


2
ตามที่ระบุไว้สิ่งนี้ไม่ทำงานสำหรับองค์ประกอบที่มีอาร์เรย์ที่ว่างเปล่า
Arthur

30

สำหรับ PHP 4.2.0 หรือใหม่กว่า:

function is_multi($array) {
    return (count($array) != count($array, 1));
}

ไม่ทำงานarray(array())หรือarray(array(), array())อย่างใดอย่างหนึ่ง โดยทั่วไปถ้าอาร์เรย์ภายในว่างเปล่าการนับซ้ำจะเพิ่ม 0 อย่างถูกต้องดังนั้นจึงทำให้ตรงกับการนับปกติ
Fanis Hatzidakis

13

ฉันคิดว่านี่เป็นวิธีที่ตรงไปตรงมาที่สุดและเป็นสุดยอด:

function is_multidimensional(array $array) {
    return count($array) !== count($array, COUNT_RECURSIVE);
}

9

คุณสามารถดำเนินการนี้:

if (count($myarray) !== count($myarray, COUNT_RECURSIVE)) return true;
else return false;

หากพารามิเตอร์โหมดทางเลือกถูกตั้งค่าเป็นCOUNT_RECURSIVE(หรือ 1) count () จะนับอาร์เรย์ซ้ำ สิ่งนี้มีประโยชน์อย่างยิ่งสำหรับการนับองค์ประกอบทั้งหมดของอาร์เรย์หลายมิติ

หากเหมือนกันหมายความว่าไม่มีระดับย่อยใด ๆ ง่ายและรวดเร็ว!


ขอบคุณ ... ที่เป็นประโยชน์ ฉันต้องการตรวจสอบว่ามีระดับย่อยในอาร์เรย์ของฉันฉันใช้if(count($tasks_by_date) !== count($tasks_by_date, 1))
Mike Barwick

เย็น. COUNT_RECURSIVE หรือ 1 เหมือนกันสำหรับ count ()
Pian0_M4n

อย่างแน่นอน ฉันชอบความยุ่งเหยิงน้อยลงและสิ่งที่!==เคยเห็นคือระดับย่อยมีอยู่ สำหรับทฤษฎีที่อาจมองหาบางสิ่งที่คล้ายกัน ... ฯลฯ
Mike Barwick

สิ่งที่คุณไม่ได้กลับมาเป็นจริงสำหรับฉัน ... ฉันต้องการที่จะเพิ่ม!==
Mike Barwick

ด้วยอาเรย์ที่ว่างเปล่าล้มเหลว
Wallace Maxters

7

คุณสามารถตรวจสอบis_array()องค์ประกอบแรกภายใต้สมมติฐานว่าหากองค์ประกอบแรกของอาร์เรย์เป็นอาร์เรย์แล้วส่วนที่เหลือของพวกเขาก็เช่นกัน


นั่นเป็นจุดที่ดีจริงๆ ในกรณีเฉพาะของฉันมันเป็น / หรือสถานการณ์ตั้งแต่ฉันควบคุมการสร้างอาร์เรย์เดิม ฉันจะเปิดคำถามไว้ในตอนนี้ในกรณีที่มีวิธีแก้ปัญหาที่อาจใช้งานได้มากกว่าปกติ
Wilco

5
เช่นนี้:if( is_array(current($arr)) ) { // is multidimensional }
Jonas Äppelgran

4

คำตอบที่ยอดเยี่ยมทั้งหมด ... นี่คือสามบรรทัดของฉันที่ฉันใช้อยู่ตลอดเวลา

function isMultiArray($a){
    foreach($a as $v) if(is_array($v)) return TRUE;
    return FALSE;
}

2

ฟังก์ชั่นนี้จะคืนค่าจำนวนอาร์เรย์ขนาด int (ถูกขโมยจากที่นี่ )

function countdim($array)
{
   if (is_array(reset($array))) 
     $return = countdim(reset($array)) + 1;
   else
     $return = 1;

   return $return;
}

สิ่งนี้จะใช้ได้กับกรณีของ Greg เท่านั้น มันไม่ใช่ทางออกทั่วไปสำหรับปัญหาที่มิติที่สองอาจอยู่ที่ใดก็ได้ในอาเรย์
Vinko Vrsalovic

$ arr = array ("hello", "hi" => "hi there"); $ arr [] = & arr; // oops
Tyzoid

2

ฉันคิดว่าคุณจะพบว่าฟังก์ชั่นนี้เป็นวิธีที่ง่ายที่สุดมีประสิทธิภาพมากที่สุดและเร็วที่สุด

function isMultiArray($a){
    foreach($a as $v) if(is_array($v)) return TRUE;
    return FALSE;
}

คุณสามารถทดสอบได้ดังนี้:

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

echo isMultiArray($a) ? 'is multi':'is not multi';
echo '<br />';
echo isMultiArray($b) ? 'is multi':'is not multi';

หากคุณกำลังจะไปหนึ่งบรรทัดอย่างน้อยก็ทำทุกอย่าง foreach($a as $v) is_array($v) ? return TRUE : return FALSE;
Robert Pounder

@RobertPounder หรือกระทั่งforeach($a as $v) return is_array($v) ? true : false;
Yassine Sedrani

2

หลังจาก PHP 7 คุณสามารถทำได้:

public function is_multi(array $array):bool
{
    return is_array($array[array_key_first($array)]);
}

1

คุณสามารถตรวจสอบง่ายๆเช่นนี้ได้:

$array = array('yo'=>'dream', 'mydear'=> array('anotherYo'=>'dream'));
$array1 = array('yo'=>'dream', 'mydear'=> 'not_array');

function is_multi_dimensional($array){
    $flag = 0;
    while(list($k,$value)=each($array)){
        if(is_array($value))
            $flag = 1;
    }
    return $flag;
}
echo is_multi_dimensional($array); // returns 1
echo is_multi_dimensional($array1); // returns 0

1

ลองดังนี้

if (count($arrayList) != count($arrayList, COUNT_RECURSIVE)) 
{
  echo 'arrayList is multidimensional';

}else{

  echo 'arrayList is no multidimensional';
}

1

แม้แต่งานนี้

is_array(current($array));

หากผิดพลาดของตนมิติเดียวอาร์เรย์ถ้าความจริงของมันหลายมิติอาร์เรย์

ปัจจุบันจะให้องค์ประกอบแรกของอาร์เรย์ของคุณและตรวจสอบว่าองค์ประกอบแรกเป็นอาร์เรย์หรือไม่โดยฟังก์ชั่นis_array


สิ่งนั้นจะไม่น่าเชื่อถือหากคุณต้องการให้แน่ใจว่าองค์ประกอบอื่น ๆ นั้นไม่ซ้อนกัน
vanamerongen

1

อย่าใช้ COUNT_RECURSIVE

คลิกเว็บไซต์นี้เพื่อทราบสาเหตุ

ใช้ rsort แล้วใช้ isset

function is_multi_array( $arr ) {
rsort( $arr );
return isset( $arr[0] ) && is_array( $arr[0] );
}
//Usage
var_dump( is_multi_array( $some_array ) );

$ arr [0] เป็นอาร์เรย์ไม่ได้ แต่ $ arr [1] อาจเป็นอาร์เรย์ได้
Supun Praneeth

1

ในกรณีของฉัน ฉันติดอยู่ในสภาพที่แปลกแตกต่างกันไป
1st case = array("data"=> "name");
2nd case = array("data"=> array("name"=>"username","fname"=>"fname"));
แต่ถ้าdataมี array แทนค่าดังนั้น sizeof () หรือ count () ฟังก์ชั่นไม่ทำงานสำหรับเงื่อนไขนี้ จากนั้นฉันสร้างฟังก์ชั่นที่กำหนดเองเพื่อตรวจสอบ
ถ้า index แรกของ array มีค่ามันจะคืนค่า "only value"
แต่ถ้า index มี array แทนที่จะเป็น value ก็จะคืนค่า "has array"
ฉันใช้วิธีนี้

 function is_multi($a) {
        foreach ($a as $v) {
          if (is_array($v)) 
          {
            return "has array";
            break;
          }
          break;
        }
        return 'only value';
    }

ขอขอบคุณเป็นพิเศษกับVinko Vrsalovic


0

ฉันคิดว่าอันนี้ดีงาม (อุปกรณ์ประกอบฉากกับผู้ใช้อื่นฉันไม่ทราบชื่อผู้ใช้ของเขา):

static public function isMulti($array)
{
    $result = array_unique(array_map("gettype",$array));

    return count($result) == 1 && array_shift($result) == "array";
}

0

วิธีการข้างต้นทั้งหมดนั้นซับซ้อนเกินไปสำหรับการนำออกใช้อย่างรวดเร็ว ถ้าอาเรย์นั้นแบนการทดสอบองค์ประกอบแรกควรส่งคืนค่าดั้งเดิมเช่น int, สตริงเป็นต้นหากเป็นหลายมิติก็ควรส่งคืนอาเรย์ คุณสามารถใช้สายการบินเดียวนี้ได้อย่างรวดเร็วและเรียบร้อย

echo is_array(array_shift($myArray));

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


เทคนิคนี้จะค้นหาอาร์เรย์หลายมิติเฉพาะถ้าองค์ประกอบแรกคืออาร์เรย์
Cragmonkey

ระมัดระวังการใช้array_shift()เนื่องจากจะลบองค์ประกอบแรกและรีเซ็ตคีย์ตัวเลข! ควรใช้งานได้ดีกว่าcurrent()ถ้ายังคงคันไว้สำหรับซับเดียว
Marcello Mönkemeyer

0

นอกจากคำตอบก่อนหน้าและขึ้นอยู่กับสคีมาของอาร์เรย์ที่คุณต้องการตรวจสอบ:

function is_multi_array($array=[],$mode='every_key'){

    $result = false;

    if(is_array($array)){

        if($mode=='first_key_only'){

            if(is_array(array_shift($array))){

                $result = true;
            }
        }
        elseif($mode=='every_key'){

            $result = true;

            foreach($array as $key => $value){

                if(!is_array($value)){

                    $result = false;
                    break;
                }
            }
        }
        elseif($mode=='at_least_one_key'){

            if(count($array)!==count($array, COUNT_RECURSIVE)){

                $result = true; 
            }
        }
    }

    return $result;
}


0
$is_multi_array = array_reduce(array_keys($arr), function ($carry, $key) use ($arr) { return $carry && is_array($arr[$key]); }, true);

นี่คือหนึ่งซับที่ดี มันวนซ้ำทุกปุ่มเพื่อตรวจสอบว่าค่าที่คีย์นั้นเป็นอาร์เรย์หรือไม่ สิ่งนี้จะทำให้มั่นใจได้ว่าเป็นจริง


-1
if($array[0]){
//enter your code 
}

if (isset($array[0])) { }ในการใช้งานน้อย หากคุณแน่ใจว่าดัชนีของอาร์เรย์เริ่มต้นจาก 0
Aistis

อาร์เรย์หลายมิติคืออาร์เรย์ที่มีหนึ่งหรือหลายอาร์เรย์ สิ่งนี้จะตรวจสอบเพื่อดูว่ามันมีองค์ประกอบที่มีคีย์เป็นศูนย์หรือไม่
Cragmonkey

-1
if ( array_key_exists(0,$array) ) {

// multidimensional array

}  else {

// not a multidimensional array

}

* เฉพาะอาร์เรย์เหล่านั้นที่มีดัชนีตัวเลข


อาร์เรย์หลายมิติคืออาร์เรย์ที่มีหนึ่งหรือหลายอาร์เรย์ สิ่งนี้จะตรวจสอบเพื่อดูว่ามันมีองค์ประกอบที่มีคีย์เป็นศูนย์หรือไม่
Cragmonkey

-1

ฟังก์ชัน print_r ดั้งเดิมส่งคืนสตริงที่มนุษย์สามารถอ่านได้ เพียงนับอินสแตนซ์ "Array"

ลอง...

substr_count(print_r([...array...], true), 'Array') > 1;

$a = array(1 => 'a',2 => 'b',3 => array(1,2,3));
$b = array(1 => 'a',2 => 'b');
$c = array(1 => 'a',2 => 'b','foo' => array(1,array(2)));
$d = array(array());
$e = array(1, array());
$f = array(array(), array());
$g = array("hello", "hi" => "hi there");
$h[] = $g;

var_dump(substr_count(print_r($a, true), 'Array') > 1);
...

//a: bool(true)
//b: bool(false)
//c: bool(true)
//d: bool(true)
//e: bool(true)
//f: bool(true)
//g: bool(false)
//h: bool(true)

ในกล่องของฉัน "is_multi ใช้เวลา 0.83681297302246 วินาทีใน 500,000 ครั้ง"

มารยาท: Ruach HaKodesh


-2
function isMultiArray(array $value)
{
    return is_array(reset($value));
}

นี่เป็นการทดสอบว่าองค์ประกอบแรกเป็นหลายมิติหรือไม่
Cragmonkey

-3
is_array($arr[key($arr)]); 

ไม่มีลูปธรรมดาและเรียบง่าย

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


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