Различные коллекции объектов в PHP - PullRequest
3 голосов
/ 07 июля 2010

Я часто сталкиваюсь со сценарием, в котором у меня есть две коллекции объектов (либо массив, либо класс IteratorAggregate), и мне нужно различить два списка.

Под diff я имею в виду:

  • Обнаружение дублирующихся объектов (логика обнаружения дубликатов будет варьироваться в зависимости от конкретного случая)
  • Добавить новые объекты
  • Удалить объекты, которых нет в другом списке

По сути, я ищу что-то вроде array_diff, которое работает с объектами. До сих пор я просто снова и снова писал одну и ту же логику для каждого типа коллекции. Очевидно, что поскольку условия для дублированных объектов будут отличаться от случая к случаю, единственного решения не существует. Но есть ли общая модель или абстракция, которую люди нашли элегантным способом справиться с этим?

Ответы [ 2 ]

2 голосов
/ 07 июля 2010

spl_object_hash поможет вам определить, совпадают ли два объекта.

1 голос
/ 08 июля 2010

Начиная с PHP5.2 существует собственная коллекция объектов с SplObjectStorage :

Класс SplObjectStorage предоставляет карту от объектов к данным или, игнорируя данные, набор объектов. Это двойное назначение может быть полезным во многих случаях, связанных с необходимостью уникальной идентификации объектов.

Пример

$obj1 = new StdClass; $obj1->prop = 1;
$obj2 = new StdClass; $obj2->prop = 2;
$obj3 = new StdClass; $obj3->prop = 3;
$obj4 = new StdClass; $obj4->prop = 4;
$obj5 = new StdClass; $obj5->prop = 5;

$collection1 = new SplObjectStorage;
$collection1->attach($obj1);
$collection1->attach($obj2);
$collection1->attach($obj3);

$collection2 = new SplObjectStorage;
$collection2->attach($obj3);
$collection2->attach($obj4);
$collection2->attach($obj5);   

SplObjectStorage реализует Countable, Iterator, Traversable, Serializable и ArrayAccess (начиная с 5.3), поэтому вы можете выполнять итерации по нему так же легко, как и по любому другому Traversable. Один и тот же объект не может появляться дважды в SplObjectStorage, если он используется в качестве набора объектов. Вы можете легко сравнить две коллекции с помощью следующей функции:

function collection_diff(SplObjectStorage $c1, SplObjectStorage $c2)
{
    $diff = new SplObjectStorage;
    foreach($c1 as $o) {
        if(!$c2->contains($o)) {
            $diff->attach($o);
        }
    }
    return $diff;
}

Конечно, вы можете настроить это, чтобы использовать пользовательское сравнение. Использование простое:

$diff = collection_diff($collection1, $collection2);
var_dump( $diff ); // will contain $obj1 and $obj2

Дальнейшее чтение:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...