Clint Lo
Clint Lo

Reputation: 45

Get earliest Y-m-d date value in a multidimensional array from qualifying rows

I want to get the minimum date from the date column of a multidimensional array, but only from rows with keycode of 0001.

How would I achieve that?

$a = [
  "a" => ['keycode' => '0001','date' => "2015-09-08"],
  "b" => ['keycode' => '0002','date' => "2015-09-05"],
  "c" => ['keycode' => '0003','date' => "2015-09-04"],
  "d" => ['keycode' => '0001','date' => "2015-09-01"],
  "e" => ['keycode' => '0001','date' => "2015-08-01"]
];

Expected result: 2015-08-01

Upvotes: 0

Views: 1175

Answers (5)

mickmackusa
mickmackusa

Reputation: 47934

Because your date expression are already in Y-m-d, they are instantly comparable as simple strings. This means that there is no need to call strtotime() for any part of this task.

If you prefer usort(), you can sort on two criteria. The following snippet will first sort on the keycode and put all 0001 rows at the front and everything else toward the back of the array. When a tiebreak is required, the second sorting rule is to compare the dates ASC.

When finished, the first occurring row will either be the 0001 row with the smallest date value or it won't be a 0001 row because there weren't any in the input array.

Code: (Demo)

$array = [
  "a" => ['keycode' => '0001','date' => "2015-09-08"],
  "b" => ['keycode' => '0002','date' => "2015-09-05"],
  "c" => ['keycode' => '0003','date' => "2002-12-04"],
  "d" => ['keycode' => '0001','date' => "2015-09-01"],
  "e" => ['keycode' => '0001','date' => "2015-10-01"]
];

$needle = '0001';

usort($array, fn($a, $b) => [$a['keycode'] !== $needle, $a['date']] <=> [$b['keycode'] !== $needle, $b['date']]);

echo $array[0]['keycode'] === $needle ? $array[0]['date'] : "No qualifying rows for $needle";
// 2015-09-01

If you'd rather see a classic loop, then this approach will conditionally update a temporary variable. (Demo)

$needle = '0001';

$earliest = null;
foreach ($array as $row) {
    if ($row['keycode'] === $needle && (!$earliest || $row['date'] < $earliest)) {
        $earliest = $row['date'];
    }
}
echo $earliest ?? "No qualifying rows for $needle"; // 2015-09-01

Upvotes: 0

Andrew
Andrew

Reputation: 2985

If the array is already sorted and you are using php 5.5.0+, then you can try this

$arr = array_column($a, "date", "keycode");
echo $arr["0001"] // string(10) "2015-08-01"

Upvotes: 0

mopo922
mopo922

Reputation: 6381

You can do this with a combination of array_filter and uasort:

function getMinDateByKeycode(array $a, $keycode)
{
    // Filter out elements by keycode
    $aFiltered = array_filter($a, function($aItem) use ($keycode) {
        return $aItem['keycode'] === $keycode;
    });

    // Sort lowest date first
    uasort($aFiltered, function($a1, $a2){
        return strtotime($a1['date']) - strtotime($a2['date']);
    });

    // Get the key of the first element of the resulting array
    reset($aFiltered);
    $keyOfMinDate = key($aFiltered);

    // Return it however you want. This example returns just the date.
    return $a[$keyOfMinDate]['date'];
}

echo getMinDateByKeycode($a, '0001');
// prints '2015-08-01'

Upvotes: 1

VIDesignz
VIDesignz

Reputation: 4783

I would first extract all of the values that have a keycode of 0001 and create a new array of just those dates. Then use the php min() function.

PHP Fiddle

$a=array(
  "a" => array('keycode' => '0001','date' =>"2015-09-08"),
  "b" => array('keycode' => '0002','date' =>"2015-09-05"),
  "c" => array('keycode' => '0003','date' =>"2015-09-04"),
  "d" => array('keycode' => '0001','date' =>"2015-09-01"),
  "e" => array('keycode' => '0001','date' =>"2015-08-01")
);

$b = [];

foreach($a as $key => $value){
    if($value['keycode']=='0001'){
     $b[]=$value['date'];
    }
}

print_r($b);

echo min($b);

Upvotes: 1

Afsar
Afsar

Reputation: 3124

This will work:

function min_date($a){
 $dates = [];
 foreach($a as $key => $value){
 if($value['keycode']=='0001'){
    array_push($dates,strtotime($value['date']));
  }
 }
 return date("Y/m/d",min($dates));
}

$result = min_date($a);

Upvotes: 1

Related Questions