【问题标题】:check if array is in two multidimensional array检查数组是否在两个多维数组中
【发布时间】:2017-01-08 16:13:57
【问题描述】:

我有两个多维数组:

干草堆

$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 = array (
  0 => array (
    "child_element_id" => 12
    "answer_id" => 17
  ),
  1 => array (
    "child_element_id" => 13
    "answer_id" => 21
  )
)

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

【问题讨论】:

  • Needle 是否有常量键名?
  • 抱歉,确切地说是“child_answers”

标签: php arrays


【解决方案1】:

几乎是一个解决方案:
@shalvah 给出了一个很好的起点。但是,在建议的解决方案中,他忘记循环遍历 $needle 数组的元素,如下所示:

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

但即便如此,这也不是完全“防水”的。如果“needle”数组的元素以不同的顺序(序列)出现,serialze()-函数将产生不同的字符串并导致假阴性,如下面的示例所示:

$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!)

稍微好一点的解决方案
这个问题可以通过先对serialize之前的所有“针”数组的所有元素进行排序(ksort():按键值排序)来解决:

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

【讨论】:

  • 递归调用函数不是更简单吗?将处理后的数据作为次要属性传递?
  • @DarylGill:完全正确!即使我在我的代码中进行了 some 排序,它很可能无法在更深的“针”数组中可靠地工作。这只是根据 shalvahs 的帖子进行的“快速拍摄”。递归代码很可能是更好的方法。也许,您可以举一个小例子;-) ...
  • @cars10 在针阵列上循环? $nearr 不是 1D 而$haystack 2D 吗?
【解决方案2】:

使用in_array() 非常容易,因为 needle 可以是一个数组:

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

或许:

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

您甚至可以使用array_search(),因为您也可以使用数组作为 needle,无需运行两个循环。

使用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()两个数组的内部数组并计算交集(普通内部数组)
  • unserialize() 结果并将count()$needle 的计数进行比较

【讨论】:

    【解决方案3】:

    你可以使用这个功能:

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

    【讨论】:

      猜你喜欢
      • 2021-05-21
      • 1970-01-01
      • 2018-01-05
      • 1970-01-01
      • 2010-09-26
      • 2010-09-13
      • 1970-01-01
      • 2019-03-05
      • 2013-09-26
      相关资源
      最近更新 更多