【问题标题】:How to merge two php Doctrine 2 ArrayCollection()如何合并两个 php Doctrine 2 ArrayCollection()
【发布时间】:2012-04-22 09:55:14
【问题描述】:

是否有任何方便的方法可以让我连接两个 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 }

我只是想知道是否可以节省我对第二个集合的迭代并将每个元素一一添加到第一个集合中。

谢谢!

【问题讨论】:

  • +1 因为它是一种常用且需要的方法

标签: php symfony doctrine-orm arraycollection


【解决方案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;
}

【讨论】:

  • & 运算符是干什么用的?是不是类似于 C 语言?好吧,这当然是一个解决方案,但我期望的行为是拥有一个已经包含一些值的ArrayCollection,并使用一种方法(ArrayCollection,如果它存在的话,或者像你这样的孤立过程)来添加另一个现有ArrayCollection 的值。您的解决方案需要创建一个新的ArrayCollection,这会使过程繁重。还是谢谢!
  • & 是通过引用传递的,因为您不想更改参数。您可以重写该方法来迭代集合。此方法没有参数,因此您可以根据需要组合任意数量的集合。
  • 问题是,我动态获取我的源集合,所以我无法按照您建议的方式进行调用...
  • 我的意思是您可以编写一个方法 mergeCollections($collection1, $collection2) 将 $collection2 的内容合并到 $collection1 中,您可以在应用程序的其他地方重用 mergeCollection 函数
  • 您应该改用 array_merge()。
【解决方案2】:

你可以这样做:

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

【讨论】:

  • 我不明白为什么这会得到如此多的支持。这是完全错误的。将对象转换为数组不会调用toArray()See what happens
  • 虽然暴民心态总是很有趣,但你们中的任何人在否决它之前真的尝试过这个吗? ArrayCollection 实现了 IteratorAggregate,它允许您将集合转换为数组,它会按预期工作。
  • 感谢上帝,聪明人!
  • @Lewis:以前试过,但对我没用(我没时间研究)。这就是为什么我不得不写另一个变种
  • @Lewis :聚会有点晚了,但我又回到了那个问题,是的,我试过了,不,它不起作用,因此投反对票。
【解决方案3】:

对我来说更好(和工作)变体:

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

【讨论】:

  • 我正在尝试做同样的事情,但放入一个数组中:array_merge($merged_arr, $doct_collection->toArray());但我没有收到错误或它是否正常工作($merged_arr 为空)。有什么想法吗?
  • 也许 $merged_arr = array_merge($merged_arr, $doct_collection->toArray()) ?
  • 记住数字和关联数组之间的区别,走这条路时:覆盖与追加。
【解决方案4】:

根据Yury Pliashkou 的评论将集合添加到数组中(我知道它没有直接回答原始问题,但已经回答了,这可以帮助其他人登陆这里):

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

也许你喜欢它……也许不……我只是想把它扔出去以防有人需要它。

【讨论】:

  • 在可能的解决方案中有某种多样性总是好的。但与其他人相比,我没有看到使用您的解决方案的好处。您介意再详细描述一下吗?
  • 和其他人一样,我在需要向数组添加集合时遇到了这个问题,但我的用例需要检查空数组/集合,所以我在这里分享。
【解决方案5】:
$newCollection = new ArrayCollection((array)$collection1->toArray() + $collection2->toArray()); 

这应该比array_merge 快。当$collection2 中存在相同的键名时,将保留来自$collection1 的重复键名。不管实际值是多少

【讨论】:

  • toArray() 返回一个数组,您肯定不需要输入另一个array 的提示吗?
  • @jimbo:你是对的,但如果出于某种原因,第一个 $collection->toArray() 返回 nullfalse。您最终会遇到致命错误。
  • 公平点 - 虽然如果 Doctrine 无法转换为数组,那么 Doctrine 代码库就会出现严重错误;)
【解决方案6】:

如果您需要防止任何重复,这个 sn-p 可能会有所帮助。它使用可变参数函数参数与 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;
}

在某些情况下可能会很方便。

【讨论】:

  • 或使用$collection3 = new ArrayCollection(array_unique(array_merge($collection1->toArray(), $collection2->toArray())));
  • 是的,但是这个和另一个流行的答案做同样的事情将整个模型对象转换为数组,这限制了进一步的功能。
【解决方案7】:

使用 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

【讨论】:

  • 小提示echo $a.toArray();这个部分肯定会报错,因为toArray不是一个有效的函数。它必须至少为echo $a->toArray();。此外,最后的输出应该格式化为代码。
【解决方案8】:

注意!避免递归元素的大量嵌套。 array_unique - 具有递归嵌入限制并导致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);

【讨论】:

    猜你喜欢
    • 2012-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-27
    • 2016-06-08
    • 1970-01-01
    • 1970-01-01
    • 2019-06-05
    相关资源
    最近更新 更多