-7

I get an array of associative arrays of selected company's hierarchy combinations (Some hierarchy levels may be null).

For example, if the hierarchy goes division > department > team:

[
  0 => ["division" => "division1"]
  1 => ["division" => "division2"]
  2 => ["division" => "division1", "department" => "department10"]
  3 => ["division" => "division1", "department" => null, "team" => "team91"]
  4 => ["division" => "division1", "department" => "department10", "team" => "team85"]
  5 => ["division" => "division3", "department" => "department999"]
  6 => ["division" => "division2", "department" => "department33"]
  7 => ["division" => "division1", "department" => null, "team" => "team92"]
]

I need to reduce it to only arrays containing unique hierarchy combinations, to the lowest hierarchy possible (It might not be the correct phrasing, so if you have a better idea please edit this sentence or let me know what to update it to)

By unique I mean array of unique combinations of hierarchies without subsets of the combinations

The above sample should result in:

[
  0 => ["division" => "division1", "department" => null, "team" => "team91"]
  1 => ["division" => "division1", "department" => null, "team" => "team92"]
  2 => ["division" => "division1", "department" => "department10", "team" => "team85"]
  3 => ["division" => "division2", "department" => "department33"]
  4 => ["division" => "division3", "department" => "department999"]
]
2
  • 3
    Write some code. There is no Magic Bullet for this. You will also need to define what makes things unique more accurately that this Commented Nov 6, 2024 at 18:02
  • By unique I mean unique combinations of hierarchies without subsets of any combination. Regarding writing code: I was thinking about first iterating the arrays to create tree structures so that I'll have all possible combinations without duplicates, but then flatten it somehow, using array_walk_recursive but it seems inefficient and I'm not sure how to properly use it in this case, if it would work at all Commented Nov 6, 2024 at 23:22

2 Answers 2

2

Sort your array rows by descending size, then progressively compare the rows in the result array against each row in the input array to see if any row is completely "covered" by a result row's data. Demo

array_multisort(array_map('count', $array), SORT_DESC, $array);
$result = [];
foreach ($array as $row) {
    foreach ($result as $saved) {
        if (!array_diff_assoc($row, $saved)) {
            continue 2;
        }
    }
    $result[] = $row;
}
var_export($result);

Output:

array (
  0 => 
  array (
    'division' => 'division1',
    'department' => NULL,
    'team' => 'team91',
  ),
  1 => 
  array (
    'division' => 'division1',
    'department' => NULL,
    'team' => 'team92',
  ),
  2 => 
  array (
    'division' => 'division1',
    'department' => 'department10',
    'team' => 'team85',
  ),
  3 => 
  array (
    'division' => 'division2',
    'department' => 'department33',
  ),
  4 => 
  array (
    'division' => 'division3',
    'department' => 'department999',
  ),
)
Sign up to request clarification or add additional context in comments.

Comments

1
<?php

$data = [
    ["division" => "division1"],
    ["division" => "division2"],
    ["division" => "division1", "department" => "department10"],
    ["division" => "division1", "department" => null, "team" => "team91"],
    ["division" => "division1", "department" => "department10", "team" => "team85"],
    ["division" => "division3", "department" => "department999"],
    ["division" => "division2", "department" => "department33"],
    ["division" => "division1", "department" => null, "team" => "team92"]
];

function getHierarchyKey($item) {
    // Create a unique key for each hierarchy level by concatenating non-null values
    return implode(':', array_filter($item, function($value) { return !is_null($value); }));
}

// Step 1: Sort data by hierarchy level, from the most specific to the least specific
usort($data, function ($a, $b) {
    return count(array_filter($b, fn($v) => !is_null($v))) <=> count(array_filter($a, fn($v) => !is_null($v)));
});

// Step 2: Filter out duplicates based on the unique key
$uniqueItems = [];
foreach ($data as $item) {
    $key = getHierarchyKey($item);
    if (!isset($uniqueItems[$key])) {
        $uniqueItems[$key] = $item;  // Add the most specific hierarchy combination
    }
}

// Step 3: Get the values of unique items
$result = array_values($uniqueItems);

// Display the result
print_r($result);

Hopefully this will do what you are looking for.

So first the data is sorted so more specific (lower level) hierarchy appear first, then we store each item by its unique key, skipping duplicates on the key. resulting in what I think you are after.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.