Goncalo Feliciano
Goncalo Feliciano

Reputation: 111

Find column values in a 2d array which do not exist in a column of another 2d array

I want to find the elements in my $db array which are not found in my $rela array.

My input arrays:

$rela = [
    ['Sale'],
    ['Customer'],
    ['Sale_Fee'],
    ['Sale'],
    ['Location'],
    ['Sale'],
    ['Sale'],
    ['Sale_Iten'],
    ['Product'],
    ['Customer'],
    ['Location'],
    ['Sale_Iten'],
    ['Sale_Fee'],
    ['Region']
];
$db = [
    ['Customer'],
    ['Customer_Type'],
    ['Fee_Type'],
    ['Location'],
    ['Location_Type'],
    ['Period'],
    ['Product'],
    ['Product_Type'],
    ['Region'],
    ['Sale'],
    ['Sale_Fee'],
    ['Sale_Iten'],
    ['State']
];

My code:

function maxEntities($rela, $db){
    $maxenty = array();
    $found   = false;

     foreach ($rela as $valor1) {  
         print $valor1[0] . " |  ";
     }
    
     print " <br \>";
     foreach ($db as $valor2) {
         print  $valor2[0] . " |  ";
     }
     $maxenty = array_diff($rela[0], $db[0]);
    
     print " <br \> <br \>";
 
     foreach ($maxenty as $valor) {
         print "  " . $valor;
     }
}
   

My current output:

Sale |  Customer |  Sale_Fee |  Sale |  Location |  Sale |  Sale |  Sale_Iten |  Product |  Customer |  Location |  Sale_Iten |  Sale_Fee |  Region |  
Customer |  Customer_Type |  Fee_Type |  Location |  Location_Type |  Period |  Product |  Product_Type |  Region |  Sale |  Sale_Fee |  Sale_Iten |  State |  

  SaleNULL

My desired output will have the following values from the $db array:

Period, Customer_Type, State, Location Type, Product Type and Fee Type.

How can I solve my problem?

I also tried with foreach, but it also gives me the wrong output.

 foreach ($rela as $relaV) {
     foreach ($db as $dbV) {
         if ($dbV[0] == $relaV[0]) {
             $found = true;
         }
         if (!$found) {
             $found   = false;
             $maxenty[] = $dbV[0];  
         } 
     }
 }

in this case my output was

Customer
Customer_Type
Fee_Type
Location
Location_Type
Period
Product
Product_Type
Region

but Customer, Region, Location are in both arrays.

Upvotes: 0

Views: 63

Answers (2)

mickmackusa
mickmackusa

Reputation: 47894

  • As a functional style solution for this task, you can use array_udiff() to filter, then array_column() to isolate the first column of any retained rows from the $db array. Demo

    var_export(
        array_column(
            array_udiff($db, $rela, fn($a, $b) => $a[0] <=> $b[0]),
            0
        )
    );
    

  • A less elegant functional-style approach uses iterated calls of in_array() inside of array_filter() and two calls of array_column(). Demo

    $blacklist = array_column($rela, 0);
    var_export(
        array_column(
            array_filter($db, fn($row) => !in_array($row[0], $blacklist)),
            0
        )
    );
    

  • For a more manual process, use a classic loop with conditional element inclusion. Demo

    $blacklist = array_column($rela, 0);
    $result = [];
    foreach ($db as [$d]) {
        if (!in_array($d, $blacklist)) {
            $result[] = $d;
        }
    }
    var_export($result);
    

  • Finally, the most manual solution would be to use nested loops and conditionally deny inclusion when a match is found in the inner loop. Demo

    $result = [];
    foreach ($db as [$d]) {
        foreach ($rela as [$r]) {
            if ($d == $r) {
                continue 2;
            }
        }
        $result[] = $d;
    }
    var_export($result);
    

All snippets above generate the same correct output:

array (
  0 => 'Customer_Type',
  1 => 'Fee_Type',
  2 => 'Location_Type',
  3 => 'Period',
  4 => 'Product_Type',
  5 => 'State',
)

Upvotes: 0

BluePsyduck
BluePsyduck

Reputation: 1141

It is not very clear, how your arrays are structured. From your code so far I guess the following structures:

$rela = array(array('Sale'), array('Customer'), array('Sale_Fee'), array('Sale'), array('Location'), array('Sale'), array('Sale'), array('Sale_Iten'), array('Product'), array('Customer'), array('Location'), array('Sale_Iten'), array('Sale_Fee'), array('Region'));
$db = array(array('Customer'), array('Customer_Type'), array('Fee_Type'), array('Location'), array('Location_Type'), array('Period'), array('Product'), array('Product_Type'), array('Region'), array('Sale'), array('Sale_Fee'), array('Sale_Iten'), array('State'));

If this is the structure of your arrays, then you can use the following code to get the difference (adopted from your foreach-approach, there may be other ways):

$maxenty = array();
foreach ($db as $dbValue) {
    $found = false;
    foreach ($rela as $relaValue) {
        if ($relaValue[0] == $dbValue[0]) {
            $found = true;
            break;
        }
    }
    if (!$found) {
        $maxenty[] = $dbValue[0];
    }
}

print_r($maxenty);

This will give you the $maxenty as follows:

Array
(
    [0] => Customer_Type
    [1] => Fee_Type
    [2] => Location_Type
    [3] => Period
    [4] => Product_Type
    [5] => State
)

Upvotes: 1

Related Questions