Как объединить два php Doctrine 2 ArrayCollection ()

61

Есть ли удобный метод, который позволяет мне объединить две Doctrine ArrayCollection()? что-то вроде:

$collection1 = new ArrayCollection();
$collection2 = new ArrayCollection();

$collection1->add($obj1);
$collection1->add($obj2);
$collection1->add($obj3);

$collection2->add($obj4);
$collection2->add($obj5);
$collection2->add($obj6);

$collection1->concat($collection2);

// $collection1 now contains {$obj1, $obj2, $obj3, $obj4, $obj5, $obj6 }

Я просто хочу знать, могу ли я сохранить итерацию по 2-й коллекции и добавить каждый элемент по одному в 1-ю коллекцию.

Спасибо!

  • 3
    +1, потому что это распространенный и необходимый метод
Теги:
doctrine2
arraycollection

7 ответов

128
Лучший ответ

Лучший (и рабочий) вариант для меня:

$collection3 = new ArrayCollection(
    array_merge($collection1->toArray(), $collection2->toArray())
);
  • 0
    Лучший ответ, без сомнения.
  • 0
    Я рекомендую это решение
Показать ещё 3 комментария
13

Вы можете просто сделать:

$a = new ArrayCollection();
$b = new ArrayCollection();
...
$c = new ArrayCollection(array_merge((array) $a, (array) $b));
  • 5
    Я не понимаю, почему так много голосов. Это просто неправильно. Приведение объекта к массиву не вызывает toArray() . Посмотри что получится
  • 0
    Это не работает
Показать ещё 10 комментариев
7

Если вам необходимо предотвратить дублирование, этот фрагмент может помочь. Он использует параметр вариационной функции для использования с PHP5.6.

/**
 * @param array... $arrayCollections
 * @return ArrayCollection
 */
public function merge(...$arrayCollections)
{
    $returnCollection = new ArrayCollection();

    /**
     * @var ArrayCollection $arrayCollection
     */
    foreach ($arrayCollections as $arrayCollection) {
        if ($returnCollection->count() === 0) {
            $returnCollection = $arrayCollection;
        } else {
            $arrayCollection->map(function ($element) use (&$returnCollection) {
                if (!$returnCollection->contains($element)) {
                    $returnCollection->add($element);
                }
            });
        }
    }

    return $returnCollection;
}

Может быть удобно в некоторых случаях.

  • 1
    Или используйте $collection3 = new ArrayCollection(array_unique(array_merge($collection1->toArray(), $collection2->toArray())));
2
$newCollection = new ArrayCollection((array)$collection1->toArray() + $collection2->toArray()); 

Это должно быть быстрее, чем array_merge. Дублированные имена ключей из $collection1 сохраняются, когда в $collection2 присутствует такое же имя ключа. Независимо от того, что фактическое значение

  • 0
    toArray() возвращает массив, вам не нужно обязательно указывать другой array ?
  • 0
    @jimbo: вы правы, но если по какой-либо причине первый $collection->toArray() возвращает null или false . Вы в конечном итоге с фатальной ошибкой.
Показать ещё 1 комментарий
1

На основе Юрия Пляшку...:

function addCollectionToArray( $array , $collection ) {
    $temp = $collection->toArray();
    if ( count( $array ) > 0 ) {
        if ( count( $temp ) > 0 ) {
            $result = array_merge( $array , $temp );
        } else {
            $result = $array;
        }
    } else {
        if ( count( $temp ) > 0 ) {
            $result = $temp;
        } else {
            $result = array();
        }
    }
    return $result;
}

Может быть, вам это нравится... может быть, нет... Я просто подумал о том, чтобы выбросить его там на случай, если кому-то это понадобится.

1

Вам все равно нужно перебирать коллекции для добавления содержимого одного массива в другой. Поскольку ArrayCollection является классом-оболочкой, вы можете попробовать объединить массивы элементов при сохранении ключей, ключи массива в $collection2 переопределить любые существующие ключи в $collection1, используя вспомогательную функцию ниже:

$combined = new ArrayCollection(array_merge_maintain_keys($collection1->toArray(), $collection2->toArray())); 

/**
 *  Merge the arrays passed to the function and keep the keys intact.
 *  If two keys overlap then it is the last added key that takes precedence.
 * 
 * @return Array the merged array
 */
function array_merge_maintain_keys() {
    $args = func_get_args();
    $result = array();
    foreach ( $args as &$array ) {
        foreach ( $array as $key => &$value ) {
            $result[$key] = $value;
        }
    }
    return $result;
}
  • 0
    Для чего & оператор & ? это что-то вроде в C? Ну, конечно, это решение, но я ожидал, что поведение будет иметь ArrayCollection который уже содержит некоторые значения, и использовать метод ( ArrayCollection , если он существует, или изолированную процедуру, такую как ваша), чтобы добавить значения еще один существующий ArrayCollection . Ваше решение требует создания новой ArrayCollection , которая усложняет процесс. Спасибо, в любом случае!
  • 0
    & Является передачей по ссылке, поскольку вы не хотите изменять аргументы. Вместо этого вы можете переписать метод для перебора коллекций. У этого метода нет аргументов, поэтому вы можете объединить столько коллекций, сколько захотите.
Показать ещё 6 комментариев
0

Использование Clousures PHP5 > 5.3.0

$a = ArrayCollection(array(1,2,3));
$b = ArrayCollection(array(4,5,6));

$b->forAll(function($key,$value) use ($a){ $a[]=$value;return true;});

echo $a.toArray();

array (size=6) 0 => int 1 1 => int 2 2 => int 3 3 => int 4 4 => int 5 5 => int 6

Ещё вопросы

Сообщество Overcoder
Наверх
Меню