0

I have an array that contains this items (content):

Array
(
    [0] => Array
        (
            [id] => 53
        )

    [1] => Array
        (
            [id] => 54
        )

    [2] => Array
        (
            [id] => 60
        )
)

I want to remove all the items that have a specific id available in another array, like: $to_remove = ["53", "54", "60"], what I did is:

foreach($to_remove as $id)
{
     $key = array_search($id, array_column($content, 'id'));
     unset($content[$key]);   
}

the problem is that in the final result I have:

Array
(
    [2] => Array
        (
            [answer] => >20%
            [points] => 3
            [id] => 60
        )

)

why?

3
  • Your question isn't clear. Are you wondering why the index in the result starts at 2 instead of 0, or why the element with id => 60 is still in the array even though it should have been removed? Commented Jan 21, 2019 at 21:40
  • @Barmar I'm wondering why the id => 60 is still in the array Commented Jan 21, 2019 at 21:41
  • 1
    @teres your solution is too complicated, try 3v4l.org/YiaEF Commented Jan 21, 2019 at 21:50

3 Answers 3

2

The problem is that the array returned by array_column() doesn't use the same keys as the original array. The array it returns is indexed starting from 0, but unset doesn't reindex the array. So after you remove an element from the array, the indexes in the array are out of sync from the indexes of array_column($content, "id");

Instead of unset, use array_splice(). This adjusts all the indexes.

foreach($to_remove as $id)
{
     $key = array_search($id, array_column($content, 'id'));
     array_splice($content, $key, 1);   
}
Sign up to request clarification or add additional context in comments.

4 Comments

I need to assign array_splice?
"The problem is that the array returned by array_column() use the same keys as the original array." This is a bit misleading said. Coincidentally this is true since before unsetting the array was numbered zero-based and gapless. You could find a better formed explaination.
@teres No, array_splice is declared to reference the first parameter, so it works on the original. The code does what it should.
@Quasimodo'sclone I was missing the word "doesn't".
2

Here's a fun way:

$content = array_intersect_key($content,
                               array_diff(array_column($content, 'id'), $to_remove));

Extract the id values from the original, compute the difference with $to_remove, then compute those key differences with the original.

Comments

1

You use array_column($content, 'id') which will run 3 times due to the foreach giving you an array like this the first time.

Array
(
    [0] => 53
    [1] => 54
    [2] => 60
)

and the second time etc..

Array
(
    [0] => 54
    [1] => 60
)

.

Then array_search will return the first corresponding key for 53 the first time for which it find the key 0.

In the second loop, it searches for 54, and it finds key 0, and the third time it finds the key 1. So in your $content array, the unset will never be 2 and is not removed.

Another possibility to get your result is to use array_filter:

$content = array_filter($content, function($x) use($to_remove) {
    return !in_array($x["id"], $to_remove);
});

Php demo

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.