сравнить два массива пользовательских объектов - PullRequest
2 голосов
/ 04 октября 2011

C ++ / Python парень здесь.

Мне нужно сравнить два php-массива, содержащих определенные пользователем классы.

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

я получил "Catchable fatal error: объект класса Point не может быть преобразован в строку". Когда я пытался использовать простой

if ($mas1 == $mas2)

Я получил Ложь.

Вопросы: 1) есть ли способ перегрузить оператор сравнения для моего класса Point 2) как правильно сравнить два массива, содержащих пользовательские классы?

Спасибо.

Я использую php 5.2.11

Ответы [ 4 ]

5 голосов
/ 04 октября 2011

На самом деле 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
}
2 голосов
/ 04 октября 2011

В настоящее время единственным способом перегрузки операторов является использование operator расширения PECL . Но для array_diff() все, что вам нужно сделать, это определить __toString(), чтобы объекты можно было сравнивать как строки (см. Примечания) :

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
1 голос
/ 04 октября 2011

Одной из проблем сейчас является то, что на самом деле ваши массивы всегда будут равны, потому что определение класса 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
1 голос
/ 04 октября 2011

Я думаю, вам нужно прочитать 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...