Pull out first occurrences from array

140 Views Asked by At

I have an array:

Array
(
    [user1] => Array
    (
        [id] => 1
        [name] => 'john'
        [types] => null
    )
    [user2] => Array
    (
        [id] => 2
        [name] => 'jane'
        [types] => Array(
            [t_id] => 2
        )
    )
    [user3] => Array
    (
        [id] => 3
        [name] => 'jeff'
        [types] => null
    )
    [user4] => Array
    (
        [id] => 4
        [name] => 'steve'
        [types] => Array(
            [t_id] => 1
        )
    )
    [user5] => Array
    (
        [id] => 5
        [name] => 'rob'
        [types] => Array(
            [t_id] => 2
        )
    )

I need to find out the first user who has a t_id of 1 and the first user who has a t_id of 2

So in the above Jane would be the first user who has a t_id of 2 and Steve would be the first user who has a t_id of 1.

I know I could loop through the array:

 private $tid1;
 private $tid2;

 foreach($data as $_v) {
     if($_v['types']['t_id'] === 1) $tid1 = $_v;
     if($_v['types']['t_id'] === 2) $tid2 = $_v;
 }

This seems inefficient though, and the above would not work fully as the loop would keep going, and later occurrences of the t_id would replace the variable.

Is there a more efficient way to do this?

6

There are 6 best solutions below

5
On

You can stop the loop when you found your td's:

foreach($data as $_v) {
 if(($_v['types']['t_id'] === 1) && !$tid1) $tid1 = $_v;
 if(($_v['types']['t_id'] === 2) && !$tid2) $tid2 = $_v;

 if($tid1 && $tid2) break;
}
0
On

To fix your loop solution and stop on first occurrence you may check if you already found decision.

 if(!$tid1 && $_v['types']['t_id'] === 1) $tid1 = $_v;

'foreach' as a solution is usually efficient enough. Especially in cases when you need to look up by more than one condition.

0
On

Maybe this would work.

 foreach($data as $_v) {
   if(!$tid1 && isset($_v['types']['t_id']) && $_v['types']['t_id'] === 1) $tid1 = $_v;
   if(!$tid2 && isset($_v['types']['t_id']) && $_v['types']['t_id'] === 2) $tid2 = $_v;

   if ($tid1 && $tid2) break;
 }
0
On

My approach:

$users = [
    'user1' => [
        'id' => 1,
        'name' => 'john',
        'types' => null,
    ],
    'user2' => [
        'id' => 2,
        'name' => 'jane',
        'types' => [
            't_id' => 2
        ]
    ],
    'user3' => [
        'id' => 3,
        'name' => 'jeff',
        'types' => null
    ],
    'user4' => [
        'id' => 4,
        'name' => 'steve',
        'types' => [
            't_id' => 1
        ]
    ],
    'user5' => [
        'id' => 5,
        'name' => 'rob',
        'types' => [
            't_id' => 2
        ]
    ]
];

$first = false;
$second = false;

foreach ($users as $user) {
    if ($user['types'] != null) {
        if ($user['types']['t_id'] == 1 && $first === false) {
            $first = $user; //Steve
            continue;
        }

        if ($user['types']['t_id'] == 2 && $second === false) {
            $second = $user; //Jane
            continue;
        }
    }
  if($first && $second) 
      break;
}
echo '<pre>';
print_r($first);
print_r($second);
echo '</pre>';
0
On

Try using array_walk along with array_unique as

$result = array();
array_walk($arr, function($v,$k) use(&$result){ if($v['types'] !== null){ $result[$v['name']] = $v['types']['t_id'];};});
$users = array_unique($result);

DEMO

0
On

Have the 'target ids' in an array.

  • Scan the $user array and check if match with any 'target id'.
  • if match: add to result and remove from 'target ids'
  • Stop if 'target ids' list is empty.

Code:

$targetIds = array(3, 2, 1); // required list of ids
$result = array();

while (current($users) && !empty($targetIds)) {

    $cuKey = key($users);
    $cu = current($users);

    if (    !empty($cu['types']['t_id'])
         &&  in_array($cu['types']['t_id'], $targetIds)) { // process match

        $result[$cuKey] = $cu;
        $targetIds = array_diff($targetIds, array($cu['types']['t_id'])); // remove processed
    }

    next($users);
}

var_dump($result, $targetIds);