skip to Main Content

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

Answers


  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.

    Login or Signup to reply.
  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',
      ),
    )
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search