여러 배열 키가 있는지 확인하는 방법


87

다음 중 하나를 포함하는 다양한 배열이 있습니다.

story & message

아니면 그냥

story

배열에 스토리와 메시지가 모두 포함되어 있는지 확인하려면 어떻게해야합니까? array_key_exists()배열에서 해당 단일 키만 찾습니다.

이를 수행하는 방법이 있습니까?


2
두 경우 모두 "이야기"가 있으면 "메시지"만 확인하면되는 것 같습니다.
Wyzard

5
사용 array_intersect_key()당신은 확인하려는 배열을 확인하려는 키의 배열을 비교합니다. 출력 길이가 확인할 키 배열과 같으면 모두 존재하는 것입니다.
Michael Berkowski

Wyzard, 메시지는 포함하지만 스토리는 포함하지 않는 다른 배열이 있지만 스토리 나 스토리 및 메시지가 포함 된 배열에만 포함되는 다른 키가 있습니다. 감사합니다
라이언

여기서 키와 값을 혼동하고 있습니까? 배열은 같은 포맷 ["story & message" => "value"]이상의처럼입니다["story & message"]
GordonM

답변:


69

확인해야 할 키가 2 개 뿐인 경우 (원래 질문에서와 같이) 키가 있는지 확인하기 위해 array_key_exists()두 번만 호출하는 것이 쉽습니다 .

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
사람들이 어레이에 두 개의 멤버가 있는지 확인하는 데 다른 솔루션이 더 좋다고 생각한다면 명확하게 읽을 수있는 코드 나 성능을 좋아하지 않아야합니다. :)
alex

필요한 키가 상대적으로 적은 경우 가장 간단한 솔루션 일 것입니다. 20 또는 30과 같은 경우 읽을 수없는 경우.
apokryfos

1
@apokryfos 동의하지만 OP의 질문에 대답합니다.
alex

2
@alex 유일한 문제는 안에없는 하나의 요소와 그 안에있는 다른 요소가$keys 포함 된 경우 빈 => ( 3v4l 예 )를 반환 한다는 것입니다 ...$arr!array_diff_keyfalse
CPHPython

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

왜 이것이 downvoted되었는지 알고 싶습니다. afaik array_intersect_key가 C로 구현되고 루프가 필요하지 않기 때문에 더 빠릅니다
Erfan

실제로 꽤 영리하고 잘했습니다. 읽기는 조금 어렵습니다.
Jon z

고마워요 :) 이상하게도 PHP에는이 작업을 수행하는 내장 함수가 없습니다. 매우 일반적입니다. 이를 수행하는 수많은 사용자 입력 유효성 검사 클래스가 있지만 대부분의 사용 사례에서 과잉 사용
Erfan

12
참으로 영리한 해결책이지만 간단한 것보다 정말 느립니다 (내 상자에서 약 50 % 느립니다).```$ ok = true; foreach ($ 필수 $ field) {if (! array_key_exists ($ field, $ data)) $ ok = false; }
Ozh dec

@Ozh를 제외하고 array_key_exists는 isset보다 느립니다
iautomation

34

의외로 array_keys_exist존재하지 않는다?! 그 사이에이 일반적인 작업에 대한 한 줄 표현을 알아 내기 위해 약간의 공간이 남습니다. 쉘 스크립트 나 다른 작은 프로그램을 생각하고 있습니다.

참고 : 다음 각 솔루션 […]은 PHP 5.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()인수 2에 없는 인수 1에있는 항목의 배열을 리턴합니다 . 따라서 빈 배열은 모든 키가 발견되었음을 나타냅니다. PHP 5.5에서는 0 === count(…)간단하게 empty(…).

array_reduce + 설정 해제

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 요소로 끝날 것으로 예상 할 수 있습니다.

우리가 관심이있는 키가 하단 라인에 잘 맞기 때문에 구성을 수정하기 쉽습니다.

배열 _ 필터배열 내

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
작은 세트의 경우 차이는 무시할 수 있습니다. 대규모 데이터 세트를 처리하는 라이브러리 / 프레임 워크를 작성하는 경우 조기 최적화보다는 병목 현상을 찾기 위해 각 유닛의 성능을 테스트해야합니다.
Mark Fox

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

8

한 가지 더 가능한 해결책 :

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솔루션 보다 두 배 이상 빠릅니다 .

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

(1000000 반복의 경우 344ms 대 768ms)


isset은 [ 'key'=> null]이면 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
나는 백만 개의 키에 대해 +/- 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 () 사용은 한 번에 하나의 키만 확인하는 것을 지원하므로 두 가지 모두 별도로 확인해야합니다.

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

나는 그것을 @Xorifelse에서 테스트 해보기 쓴 테스트를 하고 내가 틀렸다면 수정하시기 바랍니다. 참고 : 그 당시에는 PHP 5.6. * 버전 만 알고 있었기 때문에 해당 버전 만 사용했습니다.
데이비드 Dutkovsky

그 코드는 무엇을 달성하려고합니까? foreach루프를 사용하지 않는 이유는 무엇 입니까?
Xorifelse

isset기능이 내 뜻대로 작동 한다는 증명을 추가하고 싶었지만 이제는 당신이 옳았다는 것을 깨닫고 키는 여전히 배열에 남아 있으므로 내 대답이 올바르지 않습니다. 피드백에 감사드립니다. 예, 사용할 수 있습니다 foreach.
데이비드 Dutkovsky

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

배열에 여러 키가 모두 존재하는지 확인해야한다고 가정합니다. 하나 이상의 키와 일치하는 것을 찾고 있다면 다른 기능을 제공 할 수 있도록 알려주세요.

여기 코드 패드 http://codepad.viper-7.com/AKVPCH


1
해결책은 괜찮지 만 멋진 한 줄 보석이 ​​묻혀 있습니다.if (0 === count(array_diff(['key1','key2','key3'], array_keys($lookIn)))) { // all keys exist } else { // nope }
Mark Fox

당신이 쓴 것은 사실입니다. 장황하지만 내 기능이 더 읽기 쉽다는 것을 알았습니다. 물론 나는 착각 할 수있다. 내 대답에 대해 의견을 보내 주셔서 감사합니다. 나는 새로운 것을 배운다.
Kim Stacks

1

도움이 되었기를 바랍니다:

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

1

이것은 오래되었고 아마도 묻히게 될 것이지만 이것이 나의 시도입니다.

@Ryan과 비슷한 문제가 있습니다. 적어도 1 키 배열이라면 어떤 경우에는, I에서만 확인이 필요하고, 경우에 따라, 모든 필요한 존재한다.

그래서이 함수를 작성했습니다.

/**
 * 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를 검사하는 슈퍼 코드를 작성하지 않을 때는 항상 $를 잊어 버립니다. =)
Kiwi

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에 대한 검사에 유의하십시오. 검색하려는 값이 다른 경우 변경할 수 있습니다.

이 솔루션은 효율적이지 않을 수 있지만 작동합니다!

업데이트

하나의 지방 기능에서 :

 /**
 * 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;
    }

이것은 이것을 출력합니다

"필수": [ "사용자 이름", "비밀번호", "기타 필드"]

따라서이 함수가하는 일은 게시 요청의 모든 누락 된 필드를 확인하고 반환하는 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.