0

I have a question about determining whether a PHP associative array, which contains indices to another array, is a subset of another similarly constructed associative array, namely one that contains indices to another array.

Assuming that I have two arrays, one named dogs and another named legged-animals.

<?php 
$dogs = array(0 => array('height' => 100, 'weight' => 100), 
              1 => array('height' => 50, 'weight' => 50));

$legged-animals = array(0 => array('height' => 200, 'weight' => 500), 
                        1 => array('height' => 220, 'weight' => 500), 
                        2 => array('height' => 100, 'weight' => 100), 
                        3 => array('height' => 50, 'weight' => 50));
?>

So the question is, how can I determine that dogs is a subset of legged-animals?

EDIT: Here's my attempt at finding out whether one is the subset of the other:

function filter($largeSets, $subSets)
{
    $result = array();

    $count = count($subSets);
    foreach ($largeSets as $individualSet)
    {
        foreach ($subSets as $set)
        {
            $intersection = array_intersect($individualSet, $set);

            if (!empty($intersection) && isset($intersection['height']) && isset($intersection['weight']))
            {
                $result['array'][] = $individualSet;
                $count--;
                break;
            }
        }
    }

    $result['result'] = ($count == 0);

    return $result;
}

UPDATED: This is a somewhat easier solution that I think will solve the problem. The idea is to go through the multidimensional array, serialize the arrays, and then use array_intersect.

$dogs = array(0 => array('height' => 100, 'weight' => 100), 
              1 => array('height' => 50, 'weight' => 50),
              2 => array('height' => 10, 'weight' => 25) );

$legged_animals = array(0 => array('height' => 200, 'weight' => 500), 
                        1 => array('height' => 220, 'weight' => 500), 
                        2 => array('height' => 100, 'weight' => 100), 
                        3 => array('height' => 50, 'weight' => 50));

foreach ($dogs as $dog)
{
    $arr[] = serialize($dog);
}  

foreach ($legged_animals as $animal)
{
    $arr2[]  = serialize($animal);
}
$intersection = array_intersect($arr, $arr2);
print_r($intersection);

At this point, the intersection would print out a serialized form of the intersection. To get the initial results back, you'd have to unserialize the arrays.

Is there an easier way of doing this?

4

3 回答 3

0

该解决方案非常适合我的需要:

// takes two multidimensional arrays, $arr1 and $arr2
// and returns the intersection of the two 
// @return an array that is the intersection of the two
function findIntersection($arr1, $arr2)
{
    $retArray = array();
    $firstArray = array();
    $secondArray = array();
    $intersection = array();

    foreach ($arr1 as $set)
    {
        $firstArray[] = serialize($set);
    }

    foreach ($arr2 as $set)
    {
        $secondArray[] = serialize($set);
    }

    $intersection = array_intersect($firstArray, $secondArray);

    if (!empty($intersection))
    {
        foreach ($intersection as $serializedArray)
        {
            $retArray[] = unserialize($serializedArray);
        }
    }

    return $retArray;
}
于 2013-10-10T06:36:04.133 回答
0

这个冗长的方法怎么样:

// borrowed from giosh at http://php.net/manual/en/function.array-diff-assoc.php
function array_diff_assoc_recursive($array1, $array2) {
    $difference=array();
    foreach($array1 as $key => $value) {
        if( is_array($value) ) {
            if( !isset($array2[$key]) || !is_array($array2[$key]) ) {
                $difference[$key] = $value;
            } else {
                $new_diff = array_diff_assoc_recursive($value, $array2[$key]);
                if( !empty($new_diff) )
                    $difference[$key] = $new_diff;
            }
        } else if( !array_key_exists($key,$array2) || $array2[$key] !== $value ) {
            $difference[$key] = $value;
        }
    }
    return $difference;
}

function array_is_sub($needle,$haystack)
{
  foreach ($needle as $n)
  {  
    $matched=false;
    foreach ($haystack as $h)
    {
      if (empty(array_diff_assoc_recursive($n, $h)))
      { 
         $matched=true;
         break;
      }
    }
    if (!$matched) return false;
  }
  return true;
}

$dogs = array(0 => array('height' => 100, 'weight' => 100), 
              1 => array('height' => 50, 'weight' => 50));

$legged_animals = array(0 => array('height' => 200, 'weight' => 500), 
                        1 => array('height' => 220, 'weight' => 500), 
                        2 => array('height' => 100, 'weight' => 100), 
                        3 => array('height' => 50, 'weight' => 50));

if (array_is_sub($dogs,$legged_animals)) {
  echo "Dogs is a subset of Legged_Animals.";
} else {
  echo "Dogs is NOT a subset of Legged_Animals.";
}

应该管用。

于 2013-10-09T22:33:18.827 回答
-1

array_intersect() 可以解决问题(不要在数组名称中使用破折号):

$dogs = array(0 => array('height' => 100, 'weight' => 100), 
              1 => array('height' => 50, 'weight' => 50));

$leggedanimals = array(0 => array('height' => 200, 'weight' => 500), 
                        1 => array('height' => 220, 'weight' => 500), 
                        2 => array('height' => 100, 'weight' => 100), 
                        3 => array('height' => 50, 'weight' => 50));

print_r( array_intersect( $dogs, $leggedanimals ) );
// Array ( [0] => Array ( [height] => 100 [weight] => 100 ) [1] => Array ( [height] => 50 [weight] => 50 ) )
于 2013-10-09T21:16:06.280 回答