Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

sr57's avatar
Level 39

collections 'remove' method ?

I wonder if anyone known how to 'remove' a collection from another with standard methods (I should be able to do it with foreach so it's answer I'm looking for)

$col1=collect(['a','a','2','3','3','4']);
$col2=collect(['a','2']);

expected result : ['a','3','3','4'] 
0 likes
29 replies
sr57's avatar
Level 39

Hi @tray2

Clearly not slice

and I don't see (for the moment) how to use replace (for that), I give an other example of expected result below?

$col1=collect(['a','a','2','3','3','4']);
$col2=collect(['a','3']);

expected result : ['a','2','3','4'] 
sr57's avatar
Level 39

Hi @newbie360

Ok for test2, but does not pass test 1 (unique cannot be used)

newbie360's avatar

hmm no idea xD this never happened in my project

bestmomo's avatar

Hello,

Try that :

$unique = $col1->unique();
$result = $col1->diffKeys($unique)->concat($unique->diff($col2));
sr57's avatar
Level 39

Hi @bestmomo

Thanks for your try, it passed the 2 tests but not this 3rd one

Test n°3
$col1=collect(['a','a','2','2','3','3','4']);
$col2=collect(['a','2','2']);

// expected result : ['a','3','3','4']

I want to remove (one to one removal) from col1 all values present in col2

The pseudo code with foreach should be

foreach v2 in col2
	i1 = index of first (or last, ...) value v2 in col1
	if exists i1 then remove col1[i1] 

martinbean's avatar

That makes no sense though, because you say you want to remove from $col1 all values present in $col2. Well, “a” is present in $col2 but then you’re expecting that to still be present?

So, it might be better if you just told us what you’re actually trying to achieve instead of these contrived examples that contradict what you’re saying. Give us some context.

martinbean's avatar

@sr57 Yes, and like I say, what you described you wanted is different to what you listed as the expected result!

you say you want to remove from $col1 all values present in $col2. Well, “a” is present in $col2 but then you’re expecting that to still be present?

So let’s stop talking “pseudo” code and just tell us what you’re actually trying to do.

sr57's avatar
Level 39

@martinbean

because you say you want to remove from $col2 all values present in $col2

I never said this, neither I wrote this.

I wrote this

I want to remove (one to one removal) from col1 all values present in col2

martinbean's avatar

@sr57 Yes. And “a” is present in col2 so should, by your logic, be removed. But then you say you’re expecting it to still be there?

Again, just tell us what you’re trying to do. Stop with the pseudo code nonsense, and then we can get to a solution faster.

sr57's avatar
Level 39

@martinbean

Communication is a difficult art :-)

'a' is present 2 times ins col1, and only one in col2, so with the logic I want it remains one in col1

Let's imagine col1 is a fridge with aliments and you eat some define in col2

martinbean's avatar

I’m not interested in “imagining” or messing about with pseudo code. Why can’t you just tell us what the problem is so we can help you get to the answer?

I want to remove (one to one removal) from col1 all values present in col2

Again, “a” is in col2, so by your logic should be removed.

sr57's avatar
Level 39

@martinbean

???

If there is 2 yogurts in the fridge and I eat one, it remains 1 yogurt in the fridge.

If you don't understand this, don't (want to) understand pseudo-code, ... I have no other idea.

martinbean's avatar

@sr57 I’m only going on what YOU have said.

I want to remove (one to one removal) from col1 all values present in col2

“a” is in col2 in your example. Therefore “a” should be removed.

PHP doesn’t discern between two strings with the value of “a”. They both have the same value as far as PHP is concerned. So if you say, “remove a”, then PHP is going to remove anything with the value of “a”.

So, either refactor your code to use actual entities that have identities so that entities with the same value can be distinguished between. Or show us your actual code and problem.

Your persistence in abstracting the problem with pseudo code and analogies is only making for it to take longer and expend more effort than needed to get to the actual solution.

MichalOravec's avatar
Level 75

@sr57 Working code is this

$col1 = collect(['a','a','2','3','3','4']);

$col2 = collect(['a', '2']);

$copy = clone $col2;

$result = $col1->map(function ($item) use ($copy) {
    if (in_array($item, $copy->toArray())) {
        $key = $copy->search(function ($value) use ($item) {
            return $value == $item;
        });

        $copy->pull($key);

        return;
    }
        
    return $item;
})->filter()->values()->toArray();

// result -> ['a', '3', '3', '4']

Or (it's almost same)

$col1 = collect(['a','a','2','3','3','4']);

$col2 = collect(['a', '2']);

$copy = clone $col2;

$result = $col1->map(function ($item) use ($copy) {
    if ($copy->contains($item)) {
        $key = $copy->search(function ($value) use ($item) {
            return $value == $item;
        });

        $copy->forget($key);
      
        return;
    } 
  
    return $item;
})->filter()->values()->toArray();

// result -> ['a', '3', '3', '4']
sr57's avatar
Level 39

Thanks @michaloravec

Your code passed the 3 tests.

But really not so clear/simple as a foreach loop (as given in my pseudo-code), an other solution should be in 'plain php' to count the nb per elts in both collections, do the subtraction and recreate the array/collection at the end.

I'll implement your code and mine to see in term of time consumption ... to be continued.

If sb else fond a better solution, let's know.

MichalOravec's avatar

map() use foreach behind the scene.

So I don't know why you have still a problem with my code...

sr57's avatar
Level 39

@michaloravec

map() use foreach behind the scene.

I know

I don't know why you have still a problem with my code...

I did not write this

sr57's avatar
Level 39

For your information @michaloravec @tray2 @newbie360 @bestmomo @martinbean

Duration bench (with my data)

Php foreach* : 1

@michaloravec method 1 : ~4 times more

@michaloravec method 2 : ~3 times more

*like given pseudo code ( fridge for @martinbean :-) )

	private function col_remove1($col1,$col2) {
	# inputs : 2 collections
	# output  : collection = col1 - col2
		$c1=clone $col1;
		foreach ($col2 as $e ) {
		$i=$c1->search($e);
			if ( false !== $i ) {
				$f=$c1->pull($i);
			}
		}
		$c1=$c1->values();
		return $c1;
	}
martinbean's avatar

…and we could maybe help you arrive at a more performant solution if you just showed us the actual problem.

martinbean's avatar

FFS, just tell us what the frigging problem is! You’re going to get shitty answers if you don’t actually share with us all of the details of your bloody problem!

Why are you so hesitant in showing us the actual issue?

levitorres's avatar

I also have the same question. I followed everything and it seems like its not working in my case. Hopefully someone can post an alternative way of fixing the issue. Thanks.

sr57's avatar
Level 39

HI @levitorres If you don't find the answer in this subject, open a new one, this one is close and few people will see your question.

Please or to participate in this conversation.