比较两个用户定义对象数组

时间:2011-10-03 20:35:35

标签: php arrays comparison

C ++ / Python在这里。

我需要比较两个php-arrays包含用户定义的类。

class Point
{
  var $x;
  var $y;

  function _construct($x_, $y_)
  {
    $this -> x = $x_;
    $this -> y = $y_;
  }
}

$mas1 = array(new Point(0,1),new Point(0,1),new Point(0,1));   
$mas2 = array(new Point(0,1),new Point(0,1),new Point(0,1)); 

if (array_diff($mas1,$mas2) == array())
{
  echo "they're equal\n";
}

我得到了“可捕获的致命错误:类Point的对象无法转换为字符串”。当我试图使用简单的

if ($mas1 == $mas2)

我弄错了。

问题:1)有没有办法为我的类重载比较运算符Point 2)如何正确比较包含用户定义类的两个数组?

谢谢。

我使用的是php 5.2.11

4 个答案:

答案 0 :(得分:5)

实际上,PHP不支持重载运算符。第一个比较仅测试字符串数组,而第二个比较测试对象的内部编号而不测试其内容。

你应该在这里做的是使用函数array_udiff。

此功能允许您使用回调函数比较两个数组。在此回调函数中,您可以包含所需的逻辑。此函数返回两个数组之间的差异数组。如果要检查两者是否相等,请查看返回的数组是否为空。见array_udiff()

请参阅以下示例:

class Point
{
  var $x;
  var $y;

  function _construct($x_, $y_)
  {
    $this -> x = $x_;
    $this -> y = $y_;
  }

  static function compare(Point $a, Point $b)
  {
    // Do your logic here.
    if ($a->x === $b->x && $a->x === $b->x) {
      return 0;
    }
    return ($a->x > $b->x)? 1:-1;
  }
}

$mas1 = array(new Point(0,1),new Point(0,1),new Point(0,1));   
$mas2 = array(new Point(0,1),new Point(0,1),new Point(0,1));

if(count(array_udiff($mas1, $mas2, 'Point::compare')) == 0) {
   // Eq
}
else {
  // Diff
}

答案 1 :(得分:2)

目前,重载运算符的唯一方法是使用operator PECL extension。但是,对于array_diff(),您需要做的就是定义__toString(),以便对象可以是compared as strings (参见注释)

class Point
{
   var $x;
   var $y;

   function __construct($x_, $y_)
   {
      $this -> x = $x_;
      $this -> y = $y_;
   }

   function __toString()
   {
      return "x:" . $this->x . " y:" . $this->y;
   }

}

修改

如果您要比较两个数组的相等性,array_diff()是错误的函数。您根本不需要任何超载或toString();只需比较数组:

$mas1 = array(new Point(0,1),new Point(0,1),new Point(0,1));
$mas2 = array(new Point(0,1),new Point(0,1),new Point(0,1));
$mas3 = array(new Point(0,1),new Point(1,1),new Point(0,1));

if ($mas1 == $mas2) {
   echo "MAS1 == MAS2\n";
} else {
   echo "MAS1 != MAS2\n";
}
if ($mas1 == $mas3) {
   echo "MAS1 == MAS3\n";
} else {
   echo "MAS1 != MAS3\n";
}

输出:

MAS1 == MAS2
MAS1 != MAS3

答案 2 :(得分:1)

我认为您需要阅读this

不幸的是,PHP没有提供任何方法来编写自己的比较方法,当您使用=====时,它会自动调用,但您可以通过方法调用来执行此操作,例如

class comparableObject {

  var $property1 = FALSE;
  var $property2 = FALSE;

  function looseCompare ($obj) {
    if (!is_a($obj,'comparableObject')) return FALSE;
    return $this->property1 == $obj->property1 && $this->property1 == $obj->property1;
  }
  function strictCompare ($obj) {
    if (get_class($obj) !== 'comparableObject')) return FALSE;
    return $this->property1 === $obj->property1 && $this->property1 === $obj->property1;
  }

}

$a = new comparableObject;
$b = new comparableObject;
var_dump($a->looseCompare($b)); // TRUE
var_dump($b->strictCompare($a)); // TRUE

$a->property1 = '';
var_dump($a->looseCompare($b)); // TRUE (emtpy string == FALSE)
var_dump($b->strictCompare($a)); // FALSE (emtpy string !== FALSE)

答案 3 :(得分:1)

现在的一个问题是,实际上,您的数组总是相等的,因为Point类定义是错误的。

PHP中的构造函数是__construct(两个下划线),与您所做的相反:_construct(单个下划线)。因此,您的构造函数永远不会被执行,$x$y永远不会分配给您的对象实例。

如果您修复它:

class Point
{
  var $x;
  var $y;

  function __construct($x_, $y_)
  {
    $this -> x = $x_;
    $this -> y = $y_;
  }
}

然后你就可以做到:

$mas1 = array(new Point(0,1),new Point(0,1),new Point(0,1));
$mas2 = array(new Point(0,1),new Point(0,1),new Point(0,1));
$mas3 = array(new Point(0,1),new Point(0,1),new Point(0,2));
$mas4 = array(new Point(0,1),new Point(0,1),new Point(0,1),new Point(0,1));

var_dump($mas1 == $mas2); // true
var_dump($mas2 == $mas3); // false
var_dump($mas2 == $mas4); // false