dsdtszi0520538
2017-01-08 16:13
浏览 7
已采纳

检查数组是否在两个多维数组中

I have two multidimensional arrays:

Haystack

$haystack = array (
  0 => array (
    "child_element_id" => 11
    "answer_id" => 15
  ),
  1 => array (
    "child_element_id" => 12
    "answer_id" => 17
  ),
  2 => array (
    "child_element_id" => 13
    "answer_id" => 21
  )
)

Needle

 $needle = array (
  0 => array (
    "child_element_id" => 12
    "answer_id" => 17
  ),
  1 => array (
    "child_element_id" => 13
    "answer_id" => 21
  )
)

I want to check if all the key values from array "Needle" exists in the array "Haystack". What's the best practice for this? Thank you!

图片转代码服务由CSDN问答提供 功能建议

我有两个多维数组:

Haystack

  $ haystack = array(
 0 => array(
“child_element_id”=> 11 
“answer_id”=> 15 
),  
 1 =>数组(
“child_element_id”=> 12 
“answer_id”=> 17 
),
 2 =>数组(
“child_element_id”=> 13 
“  answer_id“=> 21 
)
)
   
 
 

Needle

  $ needle = array(\  n 0 =>数组(
“child_element_id”=> 12 
“answer_id”=> 17 
),
 1 =>数组(
“child_element_id”=> 13 
“answer_id  “=> 21 
)
)
   
 
 

我想检查阵列”Haystack“中是否存在数组”Needle“中的所有键值。 这是最好的做法是什么? 谢谢!

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

3条回答 默认 最新

  • dounayan3643 2017-01-09 00:07
    已采纳

    Pretty easy using in_array() since needle can be an array:

    $found = 0;
    foreach($needle as $array) {
        if(in_array($array, $haystack, true)) {
            $found++;
        }
    }
    if($found === count($needle)) {
        echo 'all needles were found in haystack';
    }
    

    Or maybe:

    $found = true;
    foreach($needle as $array) {
        if(!in_array($array, $haystack, true)) {
            $found = false;
            break;
        }
    }
    if($found) {
        echo 'all needles were found in haystack';
    }
    

    You could even use array_search() as you can use an array for needle as well, no need to run two loops.

    Using serialize():

    if(count(array_map('unserialize',
             array_intersect(array_map('serialize', $needle), 
                             array_map('serialize',$haystack)))) == count($needle))
    {
                                 echo 'all needles were found in haystack';
    }
    
    • serialize() the inner arrays of both arrays and compute the intersection (common inner arrays)
    • unserialize() the result and compare the count() with the count of $needle
    点赞 打赏 评论
  • dpgjci27392 2017-01-08 16:49

    You could use this function:

    function array_in_array(array $needle, array $haystack) {
    foreach($needle as $nearr) {
      foreach ($haystack as $array) {
        //check arrays for equality
        if(count($needle) == count($array)) {
          $needleString = serialize($needle);
          $arrayString = serialize($array);
          if(strcmp($needleString, $arrayString) == 0 )
            return true;
          }
    }
      return false;
    }
    
    点赞 打赏 评论
  • douwen3500 2017-01-08 17:43

    almost a solution:
    @shalvah gave a good starting point. However, in the suggested solution he forgot to loop over the elements of the $needle array like shown below:

    function array_in_array($neearr,$haystack) {
      foreach ($neearr as $needle){
        foreach ($haystack as $array) {
          //check arrays for equality
          if(count($needle) == count($array)) {
            $needleString = serialize($needle);
            $arrayString = serialize($array);
            echo "$needleString||$arrayString<br>";
            if(strcmp($needleString, $arrayString) == 0 ) return true;
          }
          return false;
        }
      }
    }
    

    But even so is this not completely "water tight". In cases where elements of the "needle" arrays appear in a different order (sequence) the serialze()-function will produce differing strings and will lead to false negatives, like shown in the exampe below:

    $hay=array(array('a'=>'car','b'=>'bicycle'),
             array('a'=>'bus','b'=>'truck'),
             array('a'=>'train','b'=>'coach'));
    
    $nee1=array(array('a'=>'car','b'=>'bicycle'),
             array('a'=>'train','b'=>'coach'));
    
    $nee2=array(array('b'=>'bicycle','a'=>'car'),  // different order of elements!
             array('a'=>'train','b'=>'coach')); 
    
    echo array_in_array($nee1,$hay); // true
    echo array_in_array($nee2,$hay); // false (but should be true!)
    

    a slightly better solution
    This problem can be solved by first sorting (ksort(): sort by key value) all the elements of all the "needle" arrays before serialize-ing them:

    function array_in_array($neearr,$haystack) {
      $haystackstrarr = array_map(function($array){ksort($array);return serialize($array);},$haystack);
      foreach ($neearr as $needle){
        ksort($needle);
        $needleString = serialize($needle);
        foreach ($haystackstrarr as $arrayString){
          if(strcmp($needleString, $arrayString) == 0 ) return true;
        }
        return false;
      }
    }
    
    echo array_in_array($nee1,$hay); // true
    echo array_in_array($nee2,$hay); // true
    
    点赞 打赏 评论

相关推荐 更多相似问题