2

C++/Python guy here.

I need to compare two php-arrays containig user-defined classes.

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

i got "Catchable fatal error: Object of class Point could not be converted to string". When i tried to use simple

if ($mas1 == $mas2)

i got False.

Questions: 1) is there way to overload comparison operator for my class Point 2) how to compare two arrays containing user-defined classes correctly?

Thank you.

I use php 5.2.11

4
  • 4
    You have 8 questions and not a single accepted answer. You need to remedy this by going back to old questions, finding the correct answer and marking it as such by clicking the check mark. Commented Oct 3, 2011 at 20:37
  • WHen i do this it says i need 15 reputation in order to do this. How can i do this? Commented Oct 3, 2011 at 20:40
  • 1
    It's the check (tick) icon just below the up/down arrows that you need to click, you can do this regardless of rep Commented Oct 3, 2011 at 20:43
  • It seems i have done. Am i a good guy now? Commented Oct 3, 2011 at 20:51

4 Answers 4

5

In fact, PHP doesn't support overloaded operators. The first comparison tests only array of strings, while the second tests the internal number of the object and not its content.

What you should do here is use the function array_udiff.

This function allows you to compare two arrays using a callback function. In this callback function you can include the logical you want. This function returns an array of differences between the two arrays compared. If you want to check if both are equal, see if the returned array is empty. See array_udiff()

See the example below:

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
}
Sign up to request clarification or add additional context in comments.

1 Comment

This is what i need. But the problem is that i have empty array as result in the case of euqal AND non-equal arrays.
2

Currently the only way to overload operators is to use the operator PECL extension. But, for array_diff() all you need to do is define __toString() so that the objects can be compared as strings (see notes):

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

}

Edit:

If you are trying to compare equality of two arrays, array_diff() is the wrong function. You don't need any overloading or toString() at all; simply compare the arrays:

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

Output:

MAS1 == MAS2
MAS1 != MAS3

3 Comments

I have overloaded __toString() forming unique string representation and now i have "true" as result of comparison of any arrays (with different elements and sizes). Anyway, thank you for your answer.
Make sure you understand what array_diff() is doing: it loops through all elements of the first array and checks if they exist in the second array (and any additional arrays passed in). If an element does not exist in any of the comparison arrays, it is returned. array_diff() is not for comparing equality of arrays.
@fogbit: If you're just trying to see if two arrays are equal, you don't need any overloading. See updated answer.
1

I think you need to read this.

Unfortunately, PHP does not provide any way to write your own comparison method that will be automatically invoked when you use == or === but you could just do it with a method call, e.g.

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)

1 Comment

Thank you, i wanted to make the comparison simple & clear, but it seems i had to code comparison function by my self.
1

One problem right now is that, in fact, your arrays will always be equal because the Point class definition is wrong.

A constructor in PHP is __construct (two underscores), as opposed to what you did: _construct (single underscore). Therefore, your constructor is never executed, and $x and $y are never assigned to your object instance.

If you fix it:

class Point
{
  var $x;
  var $y;

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

Then you can simply do:

$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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.