【问题标题】:Test if one array is a subset of another测试一个数组是否是另一个数组的子集
【发布时间】:2012-08-29 21:14:49
【问题描述】:

如何确定一个数组是否是另一个数组的子集(第一个数组中的所有元素都存在于第二个数组中)?

 $s1 = "string1>string2>string3>string4>string5>string6>";
 $arr1 = explode(">", $s1);
 $s2 = "string1>string4>string5";
 $arr2 = explode(">", $s2);

 $isSubset = /* ??? */

【问题讨论】:

    标签: php arrays set


    【解决方案1】:

    简单:使用数组减法。

    在数组减法中,您将知道一个数组是否是另一个数组的子集。

    例子:

    if (!array_diff($array1, $array2)) {
        // $array1 is a subset of $array2
    }
    

    参考:array_diff

    您也可以使用array_intersect

    【讨论】:

    • array_diff(['a', 'b', 'c'], ['a', 'b']) 将返回 ['c']。然而 array_diff(['c'], ['d']) 也会返回 ['c'] 所以它实际上并不是一个优雅的解决方案。
    • array_diff_assoc 在比较多维数组时更安全,如果您对数组中的每个键都有特定的类型
    • @aleemb 我不明白你的意思。对于此解决方案:array_diff(['a', 'b','c'], ['a', 'b']) 返回['c'],这意味着 array1 不是 array2 的子集 --> 正确。 array_diff(['c'], ['d']) 返回 ['c'],这意味着 array1 不是 array2 的子集 --> 正确。怎么了?
    • 我认为一个问题是这个解决方案很难考虑。 array_intersect 解没有否定性,不涉及数学。很容易在脑海中想象。
    • 但是 array_diff 将两者都转换为字符串,所以如果你有两个对象数组,你会得到错误“类_____的对象无法转换为字符串”
    【解决方案2】:

    如果数组是精确子集则返回 true 否则返回 false 的简单函数。解决方案同样适用于二维数组。

     function is_array_subset($superArr, $subArr) {
            foreach ($subArr as $key => $value) {
                //check if keys not set in super array OR values are unequal in both array.
                if (!isset($superArr[$key]) || $superArr[$key] != $value) {
                    return false;
                }
            }
            return true;
        }
    

    【讨论】:

      【解决方案3】:
      $s1 = "1>2>3>4>5>6>7";
      
      $arr1 = explode(">",$s1);
      
      $s2 = "1>2>3";
      
      $arr2 = explode(">",$s2); 
      
      if(isSub($arr1,$arr2)){
      
               echo 'true';
      
      }else{
      
               echo 'false';
      }
      
      function isSub($a1,$a2){
      
          $num2 = count($a2);
          $sub  = $num2;
      
          for($i = 0;$i < $num2 ;$i++){
              if(in_array($a2[$i],$a1)){
                  $sub--;
              }
          }
          return ($sub==0)? true:false;
      }
      

      【讨论】:

        【解决方案4】:

        如果你从字符串开始,你可以检查strstr($fullString,$subsetStr);。但这只有在所有字符都具有相同顺序时才有效:'abcd','cd' 有效,但 'abcd','ad' 无效。

        但是,与其编写自己的自定义函数,您应该知道 PHP 有 TONS 的数组函数,因此几乎不可能没有 std 函数可以满足您的需求它要做。在这种情况下,我建议array_diff:

        $srcString = explode('>','string1>string2>string3>string4>string5');
        $subset = explode('>','string3>string2>string5');
        $isSubset = array_diff($subset,$srcString);
        //if (empty($isSubset)) --> cf comments: somewhat safer branch:
        if (!$isSubset)
        {
            echo 'Subset';
            return true;
        }
        else
        {
            echo 'Nope, substrings: '.implode(', ',$isSubset).' Didn\'t match';
            return false;
        }
        

        【讨论】:

        • 谢谢,但正如它所说:这里没有真正的区别:empty === 与false 的比较松散,所以empty($var)!$var 是可以互换的。 AFAIK 的唯一好处是,当 $var 未定义时,!$var 会引发错误。这在上面的 sn-p 中是不可能的。不过,我会编辑我的答案,以防万一有人出于某种原因决定在 array_diffif() 之间添加多行代码
        • 嗯,没错。您应该仅将empty 用于可能合法不存在的变量。否则,您将不必要地放弃 PHP 错误报告的优势。这只是您应该遵循的经验法则,通过不禁止错误报告来让您自己的生活更轻松。
        • 我不介意被否决,但我确实介意人们懒得解释为什么
        • $isSubset 应该命名为 $isntSubset,不是吗?
        【解决方案5】:

        我会创建一个较大数组的关联数组,然后遍历较小的数组,寻找非冲突,如果找到,则返回 false。

        function isSubset($arr1,$arr2){
            $map = Array();
            for ($i=0;$i<count($arr1);$i++){
              $map[$arr[$i]]=true;
            }
            for ($i=0;$i<count($arr2);$i++){
               if (!isset($map[$arr2[$i]])){
                  return false;
               }
            }
            return true;
        

        【讨论】:

        • 这是我见过的最复杂的array_flip
        • 这实际上是最简单的数组翻转方式。这几乎可以肯定是 array_flip 幕后发生的事情。但是感谢您告诉我有关该功能的信息。很高兴知道。
        【解决方案6】:
        if (array_intersect($array1, $array2) == $array1) {
            // $array1 is a subset of $array2
        }
        

        【讨论】:

        • array_intersect :) 很好的解决方案
        • 你的实际上更好。 :)
        • @Tamas 好吧,不,array_diff 实际上要优雅得多。 :)
        • array_diff(['a', 'b', 'c'], ['a', 'b']) 将返回 ['c']。然而 array_diff(['c'], ['d']) 也会返回 ['c'] 所以它实际上并不是一个优雅的解决方案。
        • @aleemb 好吧...如果array_diff 的结果不是空数组,则该数组不是另一个数组的子集。如果结果是一个空数组,则它是一个子集。因此,您示例中的结果是预期的、正确的,并且正是我们想要的。
        猜你喜欢
        • 2010-09-24
        • 1970-01-01
        • 2013-06-01
        • 1970-01-01
        • 2012-05-20
        • 2022-06-11
        • 1970-01-01
        • 2016-12-13
        • 2021-07-10
        相关资源
        最近更新 更多