如何合并两个 php 原则2数组收集()

有没有什么方便的方法可以让我把两个原则 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个集合的麻烦。

谢谢!

55337 次浏览

You still need to iterate over the Collections to add the contents of one array to another. Since the ArrayCollection is a wrapper class, you could try merging the arrays of elements while maintaining the keys, the array keys in $collection2 override any existing keys in $collection1 using a helper function below:

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

You can simply do:

$a = new ArrayCollection();
$b = new ArrayCollection();
...
$c = new ArrayCollection(array_merge((array) $a, (array) $b));

Better (and working) variant for me:

$collection3 = new ArrayCollection(
array_merge($collection1->toArray(), $collection2->toArray())
);

Add a Collection to an array, based on Yury Pliashkou's comment (I know it does not directly answer the original question, but that was already answered, and this could help others landing here):

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

Maybe you like it... maybe not... I just thought of throwing it out there just in case someone needs it.

$newCollection = new ArrayCollection((array)$collection1->toArray() + $collection2->toArray());

This should be faster than array_merge. Duplicate key names from $collection1 are kept when same key name is present in $collection2. No matter what the actual value is

If you are required to prevent any duplicates, this snippet might help. It uses a variadic function parameter for usage with 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;
}

Might be handy in some cases.

Using 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

Attention! Avoid large nesting of recursive elements. array_unique - has a recursive embedding limit and causes a PHP error Fatal error: Nesting level too deep - recursive dependency?

/**
* @param ArrayCollection[] $arrayCollections
*
* @return ArrayCollection
*/
function merge(...$arrayCollections) {
$listCollections = [];
foreach ($arrayCollections as $arrayCollection) {
$listCollections = array_merge($listCollections, $arrayCollection->toArray());
}


return new ArrayCollection(array_unique($listCollections, SORT_REGULAR));
}


// using
$a = new ArrayCollection([1,2,3,4,5,6]);
$b = new ArrayCollection([7,8]);
$c = new ArrayCollection([9,10]);


$result = merge($a, $b, $c);

Combine the spread operator to merge multiple collections, e.g. all rows in all sheets of a spreadsheet, where both $sheets and $rows are ArrayCollections and have a getRows(): Collection method

// Sheet.php
public function getRows(): Collection { return $this->rows; }


// Spreadsheet.php
public function getSheets(): Collection { return $this->sheets; }


public function getRows(): Collection
return array_merge(...$this->getSheets()->map(
fn(Sheet $sheet) => $sheet->getRows()->toArray()
));