0

I searched for solutions on here but didn't find one for my use case.

I have a big array which is built like this example:

Array
(
    [0] => Array
        (
            [Template] => page.html5
        )

    [1] => Array
        (
            [Template] => page2.html5
        )

    [2] => Array
        (
            [Template] => page.html5
        )

    [3] => Array
        (
            [Template] => page2.html5
        )

    [4] => Array
        (
            [Template] => page.html5
        )

    [5] => Array
        (
            [Template] => page2.html5
        )

    [6] => Array
        (
            [id] => 27
            [table] => tl_custom
            [type] => text
            [data] => Array
                (
                    [fragment] => example
                    [previewId] => 1
                    [isActive] => 1
                )

        )

)

I would like to remove all duplicate values for the array key "Template", but besides that I want the array to stay the way it is.

So afterwards my Array should look like:

Array
(
    [0] => Array
        (
            [Template] => page.html5
        )

    [1] => Array
        (
            [Template] => page2.html5
        )
    [6] => Array
        (
            [id] => 27
            [table] => tl_custom
            [type] => text
            [data] => Array
                (
                    [fragment] => example
                    [previewId] => 1
                    [isActive] => 1
                )

        )

)

Is there a way to achieve this without using lots of memory? Thanks for your answers :)

Machavity
  • 30,841
  • 27
  • 92
  • 100
ShibeSon
  • 79
  • 5
  • Any code to show? .... Any code attempt that uses logic? Your before and after data structure is insightful but is not a code attempt. – GetSet Sep 26 '20 at 19:49
  • You need to go through a loop and check. No built in function to do this.. – SOS9GS Sep 26 '20 at 19:51
  • @GetSet I tried with multiple ideas from other people like array_unique(array_column($array, 'Template')); or $temp = array_unique(array_column($array, 'Template')); $unique_arr = array_intersect_key($array, $temp); – ShibeSon Sep 26 '20 at 19:55
  • I'll post an easy way to do it for you shortly with comments so you follow what takes place. Before I do that though, I need you to post your input data structure in code form, not `print_r` or `var_dump`. That is add to your questions some code where you explicitly define the input array. – GetSet Sep 26 '20 at 19:57
  • Please clarify if it is or is not vital to retain the `[6]` key. I mean, you aren't deriving anything useful from it, right? So you could be just as happy with `[0], [1], [2]`? @Shibe – mickmackusa Oct 26 '20 at 23:25
  • https://3v4l.org/3QWDK – mickmackusa Oct 26 '20 at 23:31

2 Answers2

2

You could use the following logic, which uses:

array_map() to flatten the array with index keys-values, and serialize() (stringify) the last array element so we can use array_unique() on the result.

Then, to restore the stringified array, i.e. turn it back into an array, we use unserialize().

<?php
$newArr = array_unique(array_map(function ($el) {
    return $el['Template'] ?? serialize($el);
}, $arr));

// restore the last element to array
$last = array_key_last($newArr); // (PHP 7 >= 7.3.0)*
$newArr[$last] = unserialize($newArr[$last]);

*if PHP version <7.3.0 use: end($newArr); $last = key($newArr);

Output:

Array
(
    [0] => page.html5
    [1] => page2.html5
    [6] => Array
        (
            [id] => 27
            [table] => tl_custom
            [type] => text
            [data] => Array
                (
                    [fragment] => example
                    [previewId] => 1
                    [isActive] => 1
                )

        )

)

working demo

jibsteroos
  • 1,366
  • 2
  • 7
  • 13
  • I am finding many of your recent answers to be to questions that can/should be closed as duplicates. Please check for duplicates before posting an answer so that Stack Overflow volunteer curators have less redundant content to manually purge. Please read [answer] ...specifically: https://stackoverflow.com/help/how-to-answer#:~:text=have%20already%20been%20asked%20and%20answered%20many%20times%20before. – mickmackusa Oct 26 '20 at 23:32
0

The code below loops the array, marks indexes for removal and then another loop does the removals:

$templates = array(); //This will store the remove plan
for ($index = 0; $index < count($input); $index++) {
    if (isset($input[$index]["Template"])) { //Ignore items where there is no template
        if (isset($templates[$input[$index]["Template"]])) { //Let's check whether we have already seen this template
            $templates[$input[$index]["Template"]] = array(); //From now on we will find duplicates for this dude
        } else { //Mark for removal
            $templates[$input[$index]["Template"]][]=$index;
        }
    }
}

//Actual removals
foreach($templates => $index) {
    //Removing the actual element:
    unset($input[$index]["Template"]);
    //Remove the parent as well if it becomes empty
    if (!count($input[$index])) unset($input[$index]);
}

The memory need for this algorithm is:

average(element_size) * number_of_elements

Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175