I have this array:
$versions = [
'1',
'1.0.2.4',
'1.1.0',
'1.12.547.8'
];
And I want:
$versions = [
'001',
'001.000.002.004',
'001.001.000',
'001.012.547.008'
];
But, if I have this:
$versions = [
'1',
'1.12'
];
I want this:
$versions = [
'01',
'01.12'
];
In other words, each string chunk must have same len of max chunk length considering every chunk throughout the array.
Explanation:
I have an array with variable elements number. Each element is a string containing a variable amount of groups of digits -- each separated by a dot. Each digit group has a variable length. I want to pad each sequence of digits so that all array sub-groups have the same length as the max group length.
In the first example, max length is 3 (longest number: 547
), so all groups of final array have 3 digits (001, 000, ...). In the second example, max length is 2 (12
), so all groups have 2 digits (01, 01, 12).
My solution:
$max = max(
array_map(
'strlen',
call_user_func_array(
'array_merge',
array_map(
function($row) {
return explode( '.', $row );
},
$versions
)
)
)
);
foreach($versions as &$version)
{
$version = preg_replace(
'/\d*(\d{' . $max . '})/',
'\1',
preg_replace(
'/(\d+)/',
str_repeat('0', $max) . '\1',
$version
)
);
}
Explained:
$tmp = array_map(
function($row) {
return explode('.', $row );
},
$versions
);
$tmp = call_user_func_array('array_merge', $tmp);
$tmp = array_map( 'strlen', $tmp );
$max = max($tmp);
$tmp = preg_replace('/(\d+)/', str_repeat('0', $max ) . '\1', $version );
$version = preg_replace( '/\d*(\d{' . $max . '})/', '\1', $tmp);
Someone have any ideas on how to simplify the process?
Well you can just simplify everything what you already did:
First we can implode()
the array into a string and match all numbers with preg_match_all()
.
To then get the longest number we just use array_map()
with strlen()
as callback and get the longest number with max()
.
Then when you know your pad length you can go through your array with preg_replace_callback()
and pad your numbers with str_pad()
.
Code:
<?php
$versions = [ '1', '1.0.2.4', '1.1.0', '1.12.547.8' ];
preg_match_all("/\d+/", implode(".", $versions), $m);
$max = max(array_map("strlen", $m[0]));
$new = preg_replace_callback("/(\d+)/", function($m)use($max){
return str_pad($m[1], $max, "0", STR_PAD_LEFT);
}, $versions);
print_r($new);
?>