Homer_J
Homer_J

Reputation: 3323

PHP - Return only unique values from multi-array

My array contains the following:

Array ( [0] => Events - Central [1] => Central [2] => Finance [3] => 17 [5] => 11 [8] => 11  )
Array ( [0] => Events - Central [1] => Central [2] => HR [3] => 17 [5] => 11 [8] => 11 )
Array ( [0] => Events - Central [1] => Central [2] => IT [3] => 17 [5] => 11 [8] => 11  )
Array ( [0] => Events - Central [1] => London [2] => Sales [3] => 17 [5] => 11 [8] => 11  )
Array ( [0] => Events - Central [1] => London [2] => Marketing [3] => 17 [5] => 11 [8] => 11 )
Array ( [0] => Events - Central [1] => London [2] => HR [3] => 17 [5] => 11 [8] => 11  )
Array ( [0] => Piloting [1] => London [2] => HR [3] => 17 [5] => 11 [8] => 11  )
Array ( [0] => Piloting [1] => London [2] => IT [3] => 17 [5] => 11 [8] => 11  )

Now, using a simple WHILE loop allows me to loop through the array and I can easily extract the information I need but I'm struggling because I need to bring back distinct values (and I cannot change the SQL code).

The output would be a simple table like this, but notice that level 1 and 2 of the table are not repeated:

Events - Central          17
    Central               17
        Finance           11
        HR                 1
        IT                 1
    London                28
        Sales             17
        Marketing          2
        HR                 5
Piloting                  37
    London                37
       HR                 30
       IT                  7

In short, I'm trying to bring back distinct instances - if that makes sense?

Is this even possible without deconstructing the array?

I'm very concious that I may not have illustrated/ framed this question well.

Upvotes: 0

Views: 97

Answers (2)

Guillermo Phillips
Guillermo Phillips

Reputation: 2216

A slightly different take on apokryfos's answer, but a similar concept. The idea is to use the de-duping ability of array keys in PHP to build up the hierarchical array:

$data = [];
$data[] = [0 => 'Events - Central', 1 => 'Central', 2 => 'Finance', 3 => 17, 5 => 11, 8 => 11];
$data[] = [0 => 'Events - Central', 1 => 'Central', 2 => 'HR', 3 => 17, 5 => 11, 8 => 11];
$data[] = [0 => 'Events - Central', 1 => 'Central', 2 => 'IT', 3 => 17, 5 => 11, 8 => 11];
$data[] = [0 => 'Events - Central', 1 => 'London', 2 => 'Sales', 3 => 17, 5 => 11, 8 => 11];
$data[] = [0 => 'Events - Central', 1 => 'London', 2 => 'Marketing', 3 => 17, 5 => 11, 8 => 11];
$data[] = [0 => 'Events - Central', 1 => 'London', 2 => 'HR', 3 => 17, 5 => 11, 8 => 11];
$data[] = [0 => 'Piloting', 1 => 'London', 2 => 'HR', 3 => 17, 5 => 11, 8 => 11];
$data[] = [0 => 'Piloting', 1 => 'London', 2 => 'IT', 3 => 17, 5 => 11, 8 => 11];

$tree_root = [];

// map the keys in the $data array to each other
$caption_to_value_mapping = [
    0 => 3,
    1 => 5,
    2 => 8
];

foreach ($data as $datum) {
    $sub_tree = &$tree_root;
    foreach ($caption_to_value_mapping as $level_index => $value) {
        $caption = $datum[$level_index];
        if (!isset($sub_tree[$caption])) {
            $sub_tree[$caption] = ['next_level' => []];
        }
        $sub_tree[$caption]['caption'] = $caption;
        $sub_tree[$caption]['value'] = $datum[$value];
        $sub_tree = &$sub_tree[$caption]['next_level'];
    }
}

var_dump($tree_root);

You can then use $tree_root in a recursive function to build the display of the data.

Note that this is generic and will take any number of levels, as long as the $caption_to_value_mapping is maintained.

Upvotes: 1

apokryfos
apokryfos

Reputation: 40653

Here's what you can do to (a) echo the data you need and (b) create an array with said data vaguely arranged in a way you can work with:

<?php
$superArray = [
    [ "Events - Central", "Central", "Finance",   17, 0, 11, 0, 0, 11, 0 ],
    [ "Events - Central", "Central", "HR",        17, 0, 11, 0, 0, 11, 0 ],
    [ "Events - Central", "Central", "IT",        17, 0, 11, 0, 0, 11, 0 ],
    [ "Events - Central", "London",  "Sales",     17, 0, 11, 0, 0, 11, 0 ], 
    [ "Events - Central", "London",  "Marketing", 17, 0, 11, 0, 0, 11, 0 ],
    [ "Events - Central", "London",  "HR",        17, 0, 11, 0, 0, 11, 0 ],
    [ "Piloting",         "London",  "HR",        17, 0, 11, 0, 0, 11, 0  ],
    [ "Piloting",         "London",  "IT",        17, 0, 11, 0, 0, 11, 0 ]
];



usort($superArray, function ($a,$b) {
    return $a[0] == $b[0] && $a[1]==$b[1]
        ? $a[2]<=>$b[2]
        : (
            $a[0] == $b[0]
            ?$a[1]<=>$b[1]
            :$a[0]<=>$b[0]
        );
});

$lastSeen = [];
$buildArray = [];

foreach ($superArray as $array) {

    if (!isset($lastSeen[0]) || $lastSeen[0] != $array[0]) {
        $lastSeen[0] = $array[0];
        $lastSeen[1] = null;
        echo $array[0]."\t".$array[3].PHP_EOL;
        $buildArray[]= [
            "level" => 0,
            "name" => $array[0],
            "value" => $array[3]
        ];
    }
    if (!isset($lastSeen[1]) || $lastSeen[1] != $array[1]) {
        $lastSeen[1] = $array[1];
        $lastSeen[2] = null;
        echo "\t".$array[1]."\t".$array[5].PHP_EOL;
        $buildArray[]= [
            "level" => 1,
            "name" => $array[1],
            "value" => $array[5]
        ];

    }
    if (!isset($lastSeen[2]) || $lastSeen[2] != $array[2]) {
        $lastSeen[2] = $array[2];
        echo "\t\t".$array[2]."\t".$array[8].PHP_EOL;
        $buildArray[]= [
            "level" => 2,
            "name" => $array[2],
            "value" => $array[8]
        ];

    }

}


print_r($buildArray);

This will print:

Events - Central    17
    Central 11
        Finance 11
        HR  11
        IT  11
    London  11
        HR  11
        Marketing   11
        Sales   11
Piloting    17
    London  11
        HR  11
        IT  11

The array structure will be:

Array
(
    [0] => Array
        (
            [level] => 0
            [name] => Events - Central
            [value] => 17
        )

    [1] => Array
        (
            [level] => 1
            [name] => Central
            [value] => 11
        )

    [2] => Array
        (
            [level] => 2
            [name] => Finance
            [value] => 11
        )

    [3] => Array
        (
            [level] => 2
            [name] => HR
            [value] => 11
        )

    [4] => Array
        (
            [level] => 2
            [name] => IT
            [value] => 11
        )

    [5] => Array
        (
            [level] => 1
            [name] => London
            [value] => 11
        )

    [6] => Array
        (
            [level] => 2
            [name] => HR
            [value] => 11
        )

    [7] => Array
        (
            [level] => 2
            [name] => Marketing
            [value] => 11
        )

    [8] => Array
        (
            [level] => 2
            [name] => Sales
            [value] => 11
        )

    [9] => Array
        (
            [level] => 0
            [name] => Piloting
            [value] => 17
        )

    [10] => Array
        (
            [level] => 1
            [name] => London
            [value] => 11
        )

    [11] => Array
        (
            [level] => 2
            [name] => HR
            [value] => 11
        )

    [12] => Array
        (
            [level] => 2
            [name] => IT
            [value] => 11
        )

)

The idea is to first put all arrays in a combined array and then sort according to the priorities (I think they're already sorted though). Having done that you keep track on what you've seen for each level and re-construct an array based on that.

Keep in mind this is very hard-coded stuff but you could probably generalize it if you need to.

Example at: http://sandbox.onlinephpfunctions.com/code/bf92828a5561d59d503e5765cc6b566a5acc0532

Upvotes: 1

Related Questions