複数の配列キーが存在するかどうかを確認する方法


87

私はどちらかを含むさまざまな配列を持っています

story & message

あるいは単に

story

配列にストーリーとメッセージの両方が含まれているかどうかを確認するにはどうすればよいですか? array_key_exists()配列内のその単一のキーのみを検索します。

これを行う方法はありますか?


2
どちらの場合も「ストーリー」があるとしたら、本当に「メッセージ」をチェックするだけでいいようです。
Wyzard 2012年

5
array_intersect_key()検証するキーの配列を、チェックしている配列と比較します。出力の長さがチェックするキーの配列と同じである場合、それらはすべて存在します。
Michael Berkowski 2012年

Wyzard、私はメッセージを含むがストーリーを含まない他の配列を持っていますが、それらはストーリー、またはストーリーとメッセージのいずれかを含む配列にのみ含まれる他のキーを持っています。ありがとう
ライアン

ここでキーと値を混同していませんか?配列は次のようにフォーマットされ["story & message" => "value"]ていますか、それとももっと似ていますか["story & message"]
GordonM 2017年

回答:


69

チェックするキーが2つしかない場合(元の質問のように)、array_key_exists()キーが存在するかどうかを確認するために2回呼び出すだけで十分簡単です。

if (array_key_exists("story", $arr) && array_key_exists("message", $arr)) {
    // Both keys exist.
}

ただし、これは明らかに多くのキーにうまくスケールアップしません。そのような状況では、カスタム関数が役立ちます。

function array_keys_exists(array $keys, array $arr) {
   return !array_diff_key(array_flip($keys), $arr);
}

3
配列に2つのメンバーが存在するかどうかを確認するために他のソリューションの方が優れていると人々が考える場合、明確で読み取り可能なコードやパフォーマンスを好まないはずです:)
alex 2016年

必要なキーが比較的少ない場合、これはおそらく最も簡単な解決策です。読めなくなるかどうかの彼ら20または30に似ている何か
apokryfos

1
@apokryfos同意しますが、OPの質問に答えます。
アレックス2016年

2
@alex唯一の問題は、$keys含まれていない要素と$arr含まれている要素が含まれている場合、!array_diff_key空を返すことです=> false3v4lの例)...
CPHPython 2018

3
!array_diff($keys, array_keys($array));これらarray_flipの作業に伴う認知的負荷が少し少ないので、これを使用することで読みやすくなると思います。
moopet

193

多数のキーをチェックする場合でも、スケーラブルなソリューションは次のとおりです。

<?php

// The values in this arrays contains the names of the indexes (keys) 
// that should exist in the data array
$required = array('key1', 'key2', 'key3');

$data = array(
    'key1' => 10,
    'key2' => 20,
    'key3' => 30,
    'key4' => 40,
);

if (count(array_intersect_key(array_flip($required), $data)) === count($required)) {
    // All required keys exist!
}

これが反対票を投じられた理由を知りたいのですが..array_intersect_keyはCで実装されており、ループは必要ないため、これはより高速です
Erfan 2013

実際にはかなり賢く、よくできています-少し読みにくいですが。
Jon z

ありがとう:)奇妙なことに、PHPにはこれを行うための組み込み関数がありません-それは非常に一般的です。これを行うユーザー入力検証クラスはたくさんありますが、ほとんどのユースケースではやり過ぎです
Erfan 2013年

12
確かに賢い解決策ですが、単純なものよりも本当に遅いです(私のボックスでは約50%遅い): `` `$ ok = true; foreach($ required as $ field){if(!array_key_exists($ field、$ data))$ ok = false; }
Ozh 2013

@Ozhは、array_key_existsがissetよりも遅いことを除けば
iautomation 2016年

34

意外とarray_keys_exist存在しないの?!暫定的に、この一般的なタスクの1行の式を理解するためのスペースを残します。シェルスクリプトや他の小さなプログラムを考えています。

注:以下の各ソリューションは、[…]php5.4以降で使用可能な簡潔な配列宣言構文を使用しています。

array_diff + array_keys

if (0 === count(array_diff(['story', 'message', '…'], array_keys($source)))) {
  // all keys found
} else {
  // not all
}

Kim Stacksへのヒント)

このアプローチは私が見つけた中で最も簡単です。array_diff()引数1に存在し、引数2に存在しない項目の配列を返します。したがって、空の配列はすべてのキーが見つかったことを示します。php 5.5では、単純化0 === count(…)して単純にすることができますempty(…)

array_reduce + unset

if (0 === count(array_reduce(array_keys($source), 
    function($in, $key){ unset($in[array_search($key, $in)]); return $in; }, 
    ['story', 'message', '…'])))
{
  // all keys found
} else {
  // not all
}

読みにくく、変更しやすい。array_reduce()コールバックを使用して配列を反復処理し、値に到達します。私たちが興味を持っている鍵供給することにより、$initialの値$inと、その後キーを削除し、我々はすべてのキーが見つかった場合は0の要素で終わることを期待することができ、ソースで見つかりました。

関心のあるキーが収益にうまく収まるため、構造を簡単に変更できます。

array_filterin_array

if (2 === count(array_filter(array_keys($source), function($key) { 
        return in_array($key, ['story', 'message']); }
    )))
{
  // all keys found
} else {
  // not all
}

array_reduceソリューションよりも書くのは簡単ですが、編集するのは少し難しいです。array_filterは、コールバックでtrue(アイテムを新しい配列にコピー)またはfalse(コピーしない)を返すことにより、フィルター処理された配列を作成できる反復コールバックでもあります。落とし穴は、あなた2が期待するアイテムの数に変更しなければならないということです。

これはより耐久性のあるものにすることができますが、途方もない読みやすさに迫っています。

$find = ['story', 'message'];
if (count($find) === count(array_filter(array_keys($source), function($key) use ($find) { return in_array($key, $find); })))
{
  // all keys found
} else {
  // not all
}

3
小さなセットの場合、違いはごくわずかです。大量のデータセットを処理するライブラリ/フレームワークを作成している場合は、各ユニットのパフォーマンステストを行って、時期尚早に最適化するのではなく、ボトルネックを見つける必要があります。
マークフォックス

16

私には、これまでで最も簡単な方法は次のように思われます。

$required = array('a','b','c','d');

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

$missing = array_diff_key(array_flip($required), $values);

プリント:

Array(
    [c] => 2
    [d] => 3
)

これにより、どのキーが正確に欠落しているかを確認することもできます。これは、エラー処理に役立つ場合があります。


これが私がここに来た理由です!
eNeMetcH 2017年

8

もう1つの可能な解決策:

if (!array_diff(['story', 'message'], array_keys($array))) {
    // OK: all the keys are in $array
} else {
   // FAIL: some keys are not
}

7

上記の解決策は賢いですが、非常に遅いです。issetを使用した単純なforeachループは、array_intersect_keyソリューションの2倍以上高速です。

function array_keys_exist($keys, $array){
    foreach($keys as $key){
        if(!array_key_exists($key, $array))return false;
    }
    return true;
}

(1000000回の反復で344ms対768ms)


['key' => null]の場合、issetはfalseを返し、null値の配列がある場合があります。代わりにISSET array_key_existsを使用する必要があります
j4r3k

false(この場合はfalseオーバーライド)trueでのリターンが早すぎるため、ここでは反対の方法を使用する必要がありました。だから、何私のニーズのために働くことであるforeach ($keys as $key) { if (array_key_exists($key, $array)) { return true; }} return false;場合だった私のニーズany配列のキーは、別の配列に存在する...
ジェフ・

1
100万キーを超える+/- 400msを「非常に遅い」とは呼びませんが、私は人間にすぎません。
Colonelclick

3

あなたがこのようなものを持っているなら:

$stuff = array();
$stuff[0] = array('story' => 'A story', 'message' => 'in a bottle');
$stuff[1] = array('story' => 'Foo');

あなたは単にcount()

foreach ($stuff as $value) {
  if (count($value) == 2) {
    // story and message
  } else {
    // only story
  }
}

これは、これらの配列キーのみがあり、他には何もないことが確実にわかっている場合にのみ機能します。

array_key_exists()の使用は、一度に1つのキーのチェックのみをサポートするため、両方を個別にチェックする必要があります。

foreach ($stuff as $value) {
  if (array_key_exists('story', $value) && array_key_exists('message', $value) {
    // story and message
  } else {
    // either one or both keys missing
  }
}

array_key_exists()キーが配列に存在する場合はtrueを返しますが、これは実際の関数であり、入力することがたくさんあります。isset()テストされた値がNULLの場合を除いて、言語構造はほぼ同じことを行います。

foreach ($stuff as $value) {
  if (isset($value['story']) && isset($value['message']) {
    // story and message
  } else {
    // either one or both keys missing
  }
}

さらに、issetを使用すると、複数の変数を一度にチェックできます。

foreach ($stuff as $value) {
  if (isset($value['story'], $value['message']) {
    // story and message
  } else {
    // either one or both keys missing
  }
}

ここで、設定されているもののテストを最適化するには、次の「if」を使用することをお勧めします。

foreach ($stuff as $value) {
  if (isset($value['story']) {
    if (isset($value['message']) {
      // story and message
    } else {
      // only story
    }
  } else {
    // No story - but message not checked
  }
}

3

これはどうですか:

isset($arr['key1'], $arr['key2']) 

両方がnullでない場合にのみtrueを返します

nullの場合、キーは配列にありません


1
値の場合$arr['key1']または$arr['key2']null、コードは、キーがまだ存在しています。
xorifelse 2016

私はそれ@Xorifelseでテストしてください見て書いたテストをし、私が間違っている場合は、私を修正してください。参考までに:当時、私はPHP 5.6。*バージョンしか知らなかったので、それだけを知っていました。
David Dutkovsky 2017年

そのコードは何を達成しようとしていますか?なぜforeachループを使用しないのですか?
Xorifelse 2017年

isset関数が意図したとおりに機能することを証明するものを追加したかったのですが、あなたが正しかったことに気付きました。キーはまだ配列に残っているため、私の答えは正しくありません。フィードバックに感謝します。はい、使用できますforeach
David Dutkovsky 2017年

3

私はこのようなものをかなり頻繁に使用します

$wantedKeys = ['story', 'message'];
$hasWantedKeys = count(array_intersect(array_keys($source), $wantedKeys)) > 0

または必要なキーの値を見つける

$wantedValues = array_intersect_key($source, array_fill_keys($wantedKeys, 1))

2

これを試して

$required=['a','b'];$data=['a'=>1,'b'=>2];
if(count(array_intersect($required,array_keys($data))>0){
    //a key or all keys in required exist in data
 }else{
    //no keys found
  }

1

これは、クラス内で使用するために自分で作成した関数です。

<?php
/**
 * Check the keys of an array against a list of values. Returns true if all values in the list
 is not in the array as a key. Returns false otherwise.
 *
 * @param $array Associative array with keys and values
 * @param $mustHaveKeys Array whose values contain the keys that MUST exist in $array
 * @param &$missingKeys Array. Pass by reference. An array of the missing keys in $array as string values.
 * @return Boolean. Return true only if all the values in $mustHaveKeys appear in $array as keys.
 */
    function checkIfKeysExist($array, $mustHaveKeys, &$missingKeys = array()) {
        // extract the keys of $array as an array
        $keys = array_keys($array);
        // ensure the keys we look for are unique
        $mustHaveKeys = array_unique($mustHaveKeys);
        // $missingKeys = $mustHaveKeys - $keys
        // we expect $missingKeys to be empty if all goes well
        $missingKeys = array_diff($mustHaveKeys, $keys);
        return empty($missingKeys);
    }


$arrayHasStoryAsKey = array('story' => 'some value', 'some other key' => 'some other value');
$arrayHasMessageAsKey = array('message' => 'some value', 'some other key' => 'some other value');
$arrayHasStoryMessageAsKey = array('story' => 'some value', 'message' => 'some value','some other key' => 'some other value');
$arrayHasNone = array('xxx' => 'some value', 'some other key' => 'some other value');

$keys = array('story', 'message');
if (checkIfKeysExist($arrayHasStoryAsKey, $keys)) { // return false
    echo "arrayHasStoryAsKey has all the keys<br />";
} else {
    echo "arrayHasStoryAsKey does NOT have all the keys<br />";
}

if (checkIfKeysExist($arrayHasMessageAsKey, $keys)) { // return false
    echo "arrayHasMessageAsKey has all the keys<br />";
} else {
    echo "arrayHasMessageAsKey does NOT have all the keys<br />";
}

if (checkIfKeysExist($arrayHasStoryMessageAsKey, $keys)) { // return false
    echo "arrayHasStoryMessageAsKey has all the keys<br />";
} else {
    echo "arrayHasStoryMessageAsKey does NOT have all the keys<br />";
}

if (checkIfKeysExist($arrayHasNone, $keys)) { // return false
    echo "arrayHasNone has all the keys<br />";
} else {
    echo "arrayHasNone does NOT have all the keys<br />";
}

配列内にすべて存在する複数のキーをチェックする必要があると想定しています。少なくとも1つのキーの一致を探している場合は、別の機能を提供できるようにお知らせください。

コードパッドはこちらhttp://codepad.viper-7.com/AKVPCH


1
解決策は結構ですが、埋葬の素敵な1行の宝石があります:if (0 === count(array_diff(['key1','key2','key3'], array_keys($lookIn)))) { // all keys exist } else { // nope }
マーク・フォックス

あなたが書いたことは真実です。冗長ではありますが、関数が読みやすくなっています。もちろん、私は間違っている可能性があります。私の答えにコメントしてくれてありがとう。私は何か新しいことを学びます。
キムスタック2014

1

お役に立てれば:

function array_keys_exist($searchForKeys = array(), $inArray = array()) {
    $inArrayKeys = array_keys($inArray);
    return count(array_intersect($searchForKeys, $inArrayKeys)) == count($searchForKeys); 
}

1

これは古く、おそらく埋葬されるでしょうが、これは私の試みです。

@Ryanと同様の問題が発生しました。場合によっては、少なくとも1つのキーが配列内にあるかどうかを確認するだけでよく、場合によってはすべてが必要でしたが存在がありました。

だから私はこの関数を書いた:

/**
 * A key check of an array of keys
 * @param array $keys_to_check An array of keys to check
 * @param array $array_to_check The array to check against
 * @param bool $strict Checks that all $keys_to_check are in $array_to_check | Default: false
 * @return bool
 */
function array_keys_exist(array $keys_to_check, array $array_to_check, $strict = false) {
    // Results to pass back //
    $results = false;

    // If all keys are expected //
    if ($strict) {
        // Strict check //

        // Keys to check count //
        $ktc = count($keys_to_check);
        // Array to check count //
        $atc = count(array_intersect($keys_to_check, array_keys($array_to_check)));

        // Compare all //
        if ($ktc === $atc) {
            $results = true;
        }
    } else {
        // Loose check - to see if some keys exist //

        // Loop through all keys to check //
        foreach ($keys_to_check as $ktc) {
            // Check if key exists in array to check //
            if (array_key_exists($ktc, $array_to_check)) {
                $results = true;
                // We found at least one, break loop //
                break;
            }
        }
    }

    return $results;
}

これは、ライト倍になるよりもはるかに簡単だった||&&ブロック。


0

これは機能しませんか?

array_key_exists('story', $myarray) && array_key_exists('message', $myarray)

2
定数を配列にすることはできません... :)
Sven

オートコンプリートIDEをチェックするスーパーコードを記述していないときは、常に$を忘れます。=)
キウイ2012年

0
<?php

function check_keys_exists($keys_str = "", $arr = array()){
    $return = false;
    if($keys_str != "" and !empty($arr)){
        $keys = explode(',', $keys_str);
        if(!empty($keys)){
            foreach($keys as $key){
                $return = array_key_exists($key, $arr);
                if($return == false){
                    break;
                }
            }
        }
    }
    return $return;
}

//デモを実行します

$key = 'a,b,c';
$array = array('a'=>'aaaa','b'=>'ccc','c'=>'eeeee');

var_dump( check_keys_exists($key, $array));

0

それが悪い考えかどうかはわかりませんが、非常に単純なforeachループを使用して複数の配列キーをチェックします。

// get post attachment source url
$image     = wp_get_attachment_image_src(get_post_thumbnail_id($post_id), 'single-post-thumbnail');
// read exif data
$tech_info = exif_read_data($image[0]);

// set require keys
$keys = array('Make', 'Model');

// run loop to add post metas foreach key
foreach ($keys as $key => $value)
{
    if (array_key_exists($value, $tech_info))
    {
        // add/update post meta
        update_post_meta($post_id, MPC_PREFIX . $value, $tech_info[$value]);
    }
} 

0
// sample data
$requiredKeys = ['key1', 'key2', 'key3'];
$arrayToValidate = ['key1' => 1, 'key2' => 2, 'key3' => 3];

function keysExist(array $requiredKeys, array $arrayToValidate) {
    if ($requiredKeys === array_keys($arrayToValidate)) {
        return true;
    }

    return false;
}

0
$myArray = array('key1' => '', 'key2' => '');
$keys = array('key1', 'key2', 'key3');
$keyExists = count(array_intersect($keys, array_keys($myArray)));

$ myArrayに$ keys配列からのキーがあるため、trueを返します


0

これが使用できるような何か

//Say given this array
$array_in_use2 = ['hay' => 'come', 'message' => 'no', 'story' => 'yes'];
//This gives either true or false if story and message is there
count(array_intersect(['story', 'message'], array_keys($array_in_use2))) === 2;

2に対するチェックに注意してください。検索する値が異なる場合は、変更できます。

このソリューションは効率的ではないかもしれませんが、機能します!

更新

1つの脂肪機能で:

 /**
 * Like php array_key_exists, this instead search if (one or more) keys exists in the array
 * @param array $needles - keys to look for in the array
 * @param array $haystack - the <b>Associative</b> array to search
 * @param bool $all - [Optional] if false then checks if some keys are found
 * @return bool true if the needles are found else false. <br>
 * Note: if hastack is multidimentional only the first layer is checked<br>,
 * the needles should <b>not be<b> an associative array else it returns false<br>
 * The array to search must be associative array too else false may be returned
 */
function array_keys_exists($needles, $haystack, $all = true)
{
    $size = count($needles);
    if($all) return count(array_intersect($needles, array_keys($haystack))) === $size;
    return !empty(array_intersect($needles, array_keys($haystack)));

}

したがって、たとえばこれで:

$array_in_use2 = ['hay' => 'come', 'message' => 'no', 'story' => 'yes'];
//One of them exists --> true
$one_or_more_exists = array_keys_exists(['story', 'message'], $array_in_use2, false);
//all of them exists --> true
$all_exists = array_keys_exists(['story', 'message'], $array_in_use2);

お役に立てれば :)


0

私は通常、自分の投稿を検証する関数を使用しますが、これもこの質問に対する回答なので、投稿させてください。

関数を呼び出すには、次のように2つの配列を使用します

validatePost(['username', 'password', 'any other field'], $_POST))

そうすると私の関数は次のようになります

 function validatePost($requiredFields, $post)
    {
        $validation = [];

        foreach($requiredFields as $required => $key)
        {
            if(!array_key_exists($key, $post))
            {
                $validation['required'][] = $key;
            }
        }

        return $validation;
    }

これはこれを出力します

"必須":["ユーザー名"、 "パスワード"、 "その他のフィールド"]

したがって、この関数が行うことは、POSTリクエストの欠落しているすべてのフィールドを検証して返すことです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.