Reputation: 410
Search in the array for the first occurrence of a string until space, then convert it to month.
$arr = [
"May Hello",
"Jun Hello12",
"Jul 3"
];
$str = $arr[0];
$matches = [];
$pattern = '/^\w+\s/';
preg_match_all($pattern, $str, $matches);
Replace $pattern in $arr:
$pattern = [
'/^\w+\s/' => date('m', strtotime($matches[0][0])) . ' ', // fist string until space
];
$arr = preg_replace(array_keys($pattern), array_values($pattern), $arr);
echo '<pre>';
print_r($arr);
echo '</pre>';
unexpected:
Array
(
[0] => 05 7 Hello
[1] => 05 Hello12
[3] => 05 3
)
expected:
Array
(
[0] => 05 7 Hello
[1] => 06 Hello12
[3] => 07 3
)
What am I doing wrong?
Upvotes: 0
Views: 244
Reputation: 47904
Use a word boundary in the pattern to ensure that only a 3-letter word is found at the start of the string. In the closure, you can convert the fullstring match to its zero-padded month number and omit the concatenation of a trailing space.
Code: (Demo)
var_export(
preg_replace_callback('/^[A-Z][a-z]{2}\b/', fn($m) => date('m', strtotime($m[0])), $arr)
);
For better processing economy, you can keep a cache of translated month values to avoid calling two functions (or instantiating a datetime object and calling a method) to generate replacement strings each time. The closure becomes a little more verbose though. (Demo)
var_export(
preg_replace_callback(
'/^[A-Z][a-z]{2}\b/',
function($m) {
static $trans = [];
$trans[$m[0]] ??= date('m', strtotime($m[0])); // only assign / call functions if needed
return $trans[$m[0]];
},
$arr
)
);
Depending on your input strings, if the letters of the 3-letter month are guaranteed to not occur later in the string then you can create a translation array and call strtr()
to avoid regex. (Demo)
$trans = [
'Jan' => '01',
'Feb' => '02',
'Mar' => '03',
'Apr' => '04',
'May' => '05',
'Jun' => '06',
'Jul' => '07',
'Aug' => '08',
'Sep' => '09',
'Oct' => '10',
'Nov' => '11',
'Dec' => '12'
];
foreach ($arr as $v) {
echo strtr($v, $trans) . "\n";
}
Upvotes: 2
Reputation: 64
$len = count($arr);
for ($i=0; $i<$len; $i++) {
$element = $arr[$i];
$letterMonth = substr($element, 0, 3);
$dateObj = \DateTime::createFromFormat('F', $letterMonth);
$month = $dateObj->format('m');
$arr[$i] = str_replace($letterMonth, $month, $element );
}
return $arr;
Upvotes: 0
Reputation: 4784
You should use preg_replace_callback
when you want to run a function on the matched results:
$arr = [
"May Hello",
"Jun Hello12",
"Jul 3"
];
$arr = preg_replace_callback(
'/^(\w+)\s/',
function ($matches) {
return date('m', strtotime($matches[0])).' ';
},
$arr
);
echo '<pre>';
print_r($arr);
echo '</pre>';
Output:
Array
(
[0] => 05 Hello
[1] => 06 Hello12
[2] => 07 3
)
Upvotes: 2