skip to Main Content

I have 2 arrays where they have some common id values, but the keys for these id keys differ slightly.

$comps = [
  [
    'c_id' => '123',
    'status' => 'active'
  ],
  [
    'c_id' => '456',
    'status' => 'destroyed'
  ],
  [
    'c_id' => '789',
    'status' => 'active'
  ]
];

$rests = [
  [
    'r_id' => 123,
    'extra' => 'some extra info for r_id 123'
  ],
  [
    'r_id' => 456,
    'extra' => 'some extra info for r_id 456'
  ]
];

My objective here is to return all entries of the $rests array that have corresponding entries within the $comps array that have both matching ID values and a status => active.

How can one achieve this?

I have seen and used array_uintersect() in the past, however I can’t seem to get this to work in the desired way.

2

Answers


  1. You can achive this with a nested foreach loop.

    $matches = [];
    foreach ($rests as $rest) {
        foreach ($comps as $comp) {
            if ($rest['r_id'] === $comp['c_id'] && $comp['status'] === 'active') {
                $matches[] = $rest;
            }
        }
    }
    
    print_r($matches);
    

    Output

    Array
    (
        [0] => Array
            (
                [r_id] => 123
                [extra] => some extra info for r_id 123
            )
    
    )
    
    Login or Signup to reply.
  2. Here is the array_uintersect() implementation with the two rules.

    This is a good choice because PHP optimizes the comparisons by using a sorting algorithm under the hood.

    Code: (Demo)

    var_export(
        array_uintersect(
            $comps,
            $rests,
            fn($a, $b) =>
                [$a['c_id'] ?? $a['r_id'], ($a['status'] ?? 'active') === 'active']
                <=>
                [$b['c_id'] ?? $b['r_id'], ($b['status'] ?? 'active') === 'active']
        )
    );
    

    With outdated PHP: (Demo)

    var_export(
        array_uintersect(
            $comps,
            $rests,
            function($a, $b) {
                return [$a['c_id'] ?? $a['r_id'], ($a['status'] ?? 'active') === 'active']
                       <=>
                       [$b['c_id'] ?? $b['r_id'], ($b['status'] ?? 'active') === 'active'];
            }
        )
    );
    

    I don’t think that it’s shameful to pre-filter the $comps array. (Demo)

    var_export(
        array_uintersect(
            array_filter($comps, function($row) { return $row['status'] === 'active'; }),
            $rests,
            function($a, $b) {
                return ($a['c_id'] ?? $a['r_id'])
                       <=>
                       ($b['c_id'] ?? $b['r_id']);
            }
        )
    );
    

    If interested in a brute force nested loop approach, then avoid doing useless cycles by conditionally breaking and continuing. I mean, think about it, why bother looping on the rests array if the given comps array can be disqualified early. Furthermore, after you make an id match and push the data into the result array, stop the inner loop. (Demo)

    $result = [];
    foreach ($comps as $comp) {
        if ($comp['status'] !== 'active') {
            continue;
        }
        foreach ($rests as $rest) {
            if ($rest['r_id'] == $comp['c_id']) {
                $result[] = $rest;
                break;
            }
        }
    }
    var_export($result);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search