phparraysmultidimensional-arrayfilterassociative-array

Filter an array of arrays to remove rows where the entire payload is found inside another (potentially larger) row


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"]
]

Solution

  • 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',
      ),
    )