dapidmini
dapidmini

Reputation: 1625

how to get parent key from multidimensional array by key

I'm trying to get one of the 'main' array ('111', '222') where the 'expire' attribute is past from current timestamp.

my array is structured like this:

$stored = array(
  '111' => array(
    0 => array(
      'type' => 'first',
      'expire' => date('Y-m-d H:i:s', strtotime('2019-01-01 08:00:00')),
    ),
    1 => array(
      'type' => 'second',
      'expire' => date('Y-m-d H:i:s', strtotime('2019-01-01 09:00:00')),
    ),
  ),
  '222' => array(
    0 => array(
      'type' => 'first',
      'expire' => date('Y-m-d H:i:s', strtotime('2019-01-02 12:00:00')),
    ),
    1 => array(
      'type' => 'second',
      'expire' => date('Y-m-d H:i:s', strtotime('2019-01-02 13:00:00')),
    ),
    2 => array(
      'type' => 'third',
      'expire' => date('Y-m-d H:i:s', strtotime('2019-01-02 14:00:00')),
    ),
  ),
);

I did a bit of research and found array_column which I feel to be a part of the solution but I don't know how to apply it to my case since I tried

$list = array_column($stored, 'expire');
print_r($list);

and it gives an empty array, so it means array_column doesn't work on multidimensional array..

Upvotes: 0

Views: 130

Answers (3)

Gabriel
Gabriel

Reputation: 970

Using your code

// an array to hold all the expired dates
$expired = [];

$stored = array(
        '111' => array(
            0 => array(
                'type' => 'first',
                'expire' => date('Y-m-d H:i:s', strtotime('2019-08-01 08:00:00')),
            ),
            1 => array(
                'type' => 'second',
                'expire' => date('Y-m-d H:i:s', strtotime('2019-01-01 09:00:00')),
            ),
        ),
        '222' => array(
            0 => array(
                'type' => 'first',
                'expire' => date('Y-m-d H:i:s', strtotime('2019-01-02 12:00:00')),
            ),
            1 => array(
                'type' => 'second',
                'expire' => date('Y-m-d H:i:s', strtotime('2019-01-02 13:00:00')),
            ),
            2 => array(
                'type' => 'third',
                'expire' => date('Y-m-d H:i:s', strtotime('2019-01-02 14:00:00')),
            ),
        ),
);

// Loop through the first/parent array
foreach($stored as $key => $val){
    // Get the expire index only and store into variable for use in the inner loop
    $expire_dates = array_column($val, 'expire');
    // Loop through the inner arrays
    foreach($val as $value){
        // Convert the expire date from 'Y-m-d H:i:s' to unix timestamp, it is easier and better for date comparison
        $expire = strtotime($value['expire']);
        if($expire < time() ){
            $expired[$key][] = $value['expire'];
        }
    }

}

// Now print all the expired array data
echo '<pre>';
print_r($expired);

Expected Output:

Array
(
    [111] => Array
        (
            [0] => 2019-01-01 09:00:00
        )

    [222] => Array
        (
            [0] => 2019-01-02 12:00:00
            [1] => 2019-01-02 13:00:00
            [2] => 2019-01-02 14:00:00
        )

)

Upvotes: 0

Nigel Ren
Nigel Ren

Reputation: 57141

A couple of nested foreach loops are the most efficient (IMHO) as the inner loop checks for an expired entry. As soon as one is found it flags the whole key and then moves onto the next one. This saves having to process all of the entries and then check if any are left...

$expired = [];
foreach ( $stored as $key => $main )    {
    foreach ( $main as $sub )   {
        if ( strtotime($sub['expire']) < time() )   {
            $expired[] = $key;
            break;
        }
    }
}
print_r($expired);

If you just want the first expired one, then change

break;

to

break 2;

and it will stop both loops as soon as it finds an expired item.

Upvotes: 1

atymic
atymic

Reputation: 3128

You could just loop over each of the collections of items, and then use array_filter to determine if any of the items are expired. For example:

$expiredKeys = [];

foreach ($stored as $key => $items) {
    $hasExpired = count(array_filter($items, function ($item) {
        return strtotime($item['expire']) < time();
    })) > 0;

    if ($hasExpired) {
        $expiredKeys[] = $key;
    }
}

var_dump($expiredKeys);

Outputs:

array(2) {
  [0] =>
  int(111)
  [1] =>
  int(222)
}

Upvotes: 0

Related Questions