配列が多次元かどうかを確認していますか?


137
  1. 配列がプリミティブ値のフラット配列であるか、多次元配列であるかを確認する最も効率的な方法は何ですか?
  2. 実際に配列をループしis_array()て各要素で実行せずにこれを行う方法はありますか?

9
PHPには真の多次元配列がないことを指摘する価値があります-単純な連想配列の値だけです。だからあなたの質問は本当に「私の配列に非スカラー値はありますか?」
gahooa 2010年

21
実は…指摘する価値は全くないと思います。
Joe

回答:


135

簡単に言えば、「2番目の次元」がどこかにある可能性がある場合は、少なくとも暗黙的にループすることなしにそれを行うことはできません。最初のアイテムにする必要がある場合は、

is_array($arr[0]);

しかし、私が見つけることができる最も効率的な一般的な方法は、配列でforeachループを使用して、ヒットが見つかるたびに短絡することです(少なくとも暗黙的なループは、ストレートなfor()より優れています)。

$ 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
良いですが、is_arrayをベアワードとして使用するのではなく、フィルタリングラインにarray_map( "is_array"、$ a)を含める必要があると私は信じています。
Matthew Scharley、2008

is_multiを高速化した良いキャッチですが、それでもforeachに匹敵するほど十分ではありません
Vinko Vrsalovic '28

2
記述されているように、multi_3はインデックスにギャップのないゼロベースの非連想配列でのみ機能することに注意してください。つまり、これらの例は多次元として正しく識別されません。
Cragmonkey

関数is_multi()でコードを最適化するreturn count($rv)>0
Xorifelse

is_array(array_values($ arr)[0])カスタマイズされたキーの回避策として。
Vitor Rodrigues

191

count()を2回使用します。デフォルトモードで1回、再帰モードで1回。値が一致する場合、配列は多次元ではありません。これは、多次元配列の方が再帰カウントが高いためです。

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

このオプションの2番目の値modeは、PHP 4.2.0で追加されました。PHPドキュメントから:

オプションのモードパラメータがCOUNT_RECURSIVE(または1)に設定されている場合、count()は配列を再帰的にカウントします。これは、多次元配列のすべての要素を数える場合に特に役立ちます。count()は無限再帰を検出しません。

ただし、この方法では検出されませんarray(array())


2
すでに述べたように、これは空の配列を持つ要素には機能しません
アーサー

30

PHP 4.2.0以降の場合:

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

array(array())またはarray(array(), array())どちらかのために働いていません。通常、内部の配列が空の場合、再帰的なカウントは正しく0を追加するため、通常のカウントと一致します。
Fanis Hatzidakis 16年

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;

オプションのmodeパラメータがCOUNT_RECURSIVE(または1)に設定されている場合、count()は配列を再帰的にカウントします。これは、多次元配列のすべての要素を数える場合に特に役立ちます。

同じ場合は、サブレベルがどこにもないことを意味します。簡単で速い!


ありがとう...役に立ちました。アレイの下位レベルが存在することを確認したかったので、使用しましたif(count($tasks_by_date) !== count($tasks_by_date, 1))
Mike Barwick

涼しい。COUNT_RECURSIVEまたは1はcount()と同じ
15年

もちろんです。私は雑然が少ないのが好きで、!==サブレベルが存在することを確認するために使用されました。同様の何かを探しているかもしれない理論のために...など。
マイクバーウィック2015年

あなたが持っていたものは私にとって真実に戻っていません...私は追加する必要がありました!==
マイク・バーウィック

空の配列で失敗した
ウォレスマクスターズ

7

is_array()配列の最初の要素が配列である場合、残りの要素もそうであるという前提の下で、最初の要素を確認することができます。


それは実際には良い点です。私の特定のケースでは、元の配列の作成を制御しているので、どちらかまたは両方の状況です。より一般的に機能する解決策がある場合に備えて、今は質問を開いたままにしておきます。
Wilco、

5
このように:if( is_array(current($arr)) ) { // is multidimensional }
JonasÄppelgran14年

4

すべての素晴らしい答え...これは私がいつも使っている私の3行です

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

2

この関数は、配列の次元数を返します(ここから盗みます)。

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

   return $return;
}

これはグレッグの場合にのみ機能します。なお、第2の寸法は、アレイ内のどこにでも可能性があり、問題への一般的な解決策ではありません
Vinko Vrsalovic

$ arr = array( "hello"、 "hi" => "こんにちは"); $ arr [] =&arr; // oops
Tyzoid 2013

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';

1行にする場合は、少なくともすべてを行います。foreach($a as $v) is_array($v) ? return TRUE : return FALSE;
Robert Pounder 2017

@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));

もし一次元配列の場合、真マルチ次元配列。

currentはあなたの配列の最初の要素を与え、最初の要素が配列であるかどうかをis_array関数でチェックします。


他の要素もネストされていないことを確認したい場合、これは信頼できません。
バナメロンゲン2017


1

私の場合。様々な変なコンディションで立ち往生しました。
1番目のケース= array("data"=> "name");
2番目のケース= array("data"=> array("name"=>"username","fname"=>"fname"));
ただしdata、値の代わりに配列がある場合、sizeof()またはcount()関数はこの条件では機能しません。次に、チェックするカスタム関数を作成します。
配列の最初のインデックスに値がある場合、「値のみ」を返し
ますが、インデックスに値の代わりに配列がある場合、「配列あり」
を返しますこの方法を使用します

 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、stringなどのプリミティブが返されます。多次元の場合、配列を返します。ひとことで言えば、この1つのライナーをすばやくきれいに使用できます。

echo is_array(array_shift($myArray));

これがtrueを返す場合、配列は多次元です。それ以外はフラットです。ただ注意してください。配列が異なる次元を持つことは非常にまれです。たとえば、モデルからデータを生成している場合、ループが通ることができる同じタイプの多次元またはフラット構造が常にあります。 機械製ループ そうでない場合は、手作業でカスタム構築しています。つまり、すべてがどこにあるかがわかっていて、ループアルゴリズムを記述する必要なく機能します。 ここに画像の説明を入力してください


この手法は、最初の要素が配列の場合にのみ多次元配列を見つけます。
Cragmonkey 2016年

を使用すると、最初の要素が削除され、数値キーもリセットさarray_shift()れるため、注意が必要です。それでもワンライナーのかゆみがある場合は、よりよく使用してください。current()
MarcelloMönkemeyer2017

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

多次元配列は、1つ以上の配列を含む配列です。これは、ゼロのキーを持つ要素が含まれているかどうかを確認するだけです。
Cragmonkey 2016年

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

// multidimensional array

}  else {

// not a multidimensional array

}

*数値インデックスを持つ配列のみ


多次元配列は、1つ以上の配列を含む配列です。これは、ゼロのキーを持つ要素が含まれているかどうかを確認するだけです。
Cragmonkey 2016年

-1

ネイティブのprint_r関数は、人間が読める文字列を返します。「配列」インスタンスを数えるだけです。

やってみて...

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は500000回で0.83681297302246秒かかりました」

礼儀: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.