Link to home
Start Free TrialLog in
Avatar of hankknight
hankknightFlag for Canada

asked on

PHP: Undefined offset with usort and preg_match

This does not work if the array contains special characters:

<pre><?php

$arr = Array ( 'xa0.txt', 'xa1.txt', 'xa10.txt', 'xa11.txt', 'xa12.txt', 'xa2.txt', 'xa3.txt', 'xa4.txt', 'xa5.txt', 'xa6.txt', 'xa7.txt', 'xa8.txt', 'xa9.txt');
usort($arr, 'cmp');
print_r($arr);

$arr = Array ( 'a/b/c_d-e555/xa0.txt', 'a/b/c_d-e555/xa1.txt', 'a/b/c_d-e555/xa10.txt',  'a/b/c_d-e555/xb10.txt', 'a/b/c_d-e555/xb11.txt', 'a/b/c_d-e555/xb2.txt', 'a/b/c_d-e555/xb1.txt', 'a/b/c_d-e555/xa11.txt', 'a/b/c_d-e555/xa12.txt', 'a/b/c_d-e555/xa2.txt', 'a/b/c_d-e555/xa3.txt', 'a/b/c_d-e555/xa4.txt', 'a/b/c_d-e555/xa5.txt', 'a/b/c_d-e555/xa6.txt', 'a/b/c_d-e555/xa7.txt', 'a/b/c_d-e555/xa8.txt', 'a/b/c_d-e555/xa9.txt');
usort($arr, 'cmp');
print_r($arr);

function cmp($a, $b) {
    $a = zeroadd($a);
    $b = zeroadd($b);
    if ($a == $b) {
        return 0;
    }
    return ($a < $b) ? -1 : 1;
}

function zeroadd($a) {
    preg_match('/^(\w+)(\d+)(\.\w+)$/', $a, $bits);
    return sprintf("%s%05d%s",$bits[1],$bits[2],$bits[3]);
}

?></pre>

Open in new window

Avatar of Lee Wadwell
Lee Wadwell
Flag of Australia image

What do you want to sort on?
  - the entire path and file name with name adjusted to have leading zeroes; or
  - just the file name adjusted to have leading zeroes

If everything + the filename etc try the preg_match() in the zeroadd function
    preg_match('/^(.+)(\d+)(\.\w+)$/', $a, $bits);

But to depending on what you could throw at it ... the regex may need further refinement.
A slightly safer approach would to handle non-matching strings ... e.g.
function zeroadd($a) {
    if ( preg_match('/^(.+)(\d+)(\.\w+)$/', $a, $bits) )
        return sprintf("%s%05d%s",$bits[1],$bits[2],$bits[3]);
    else
        return $a;
}

Open in new window

Please answer the question asked here:
https://www.experts-exchange.com/questions/27848911/PHP-Sort-Array-Ascending-With-or-Without-Trailing-Zeros.html?anchorAnswerId=38353128#a38353128

What we're trying to get is a dialog that will lead us to an acceptably clear description of the input data and the outputs you want.  Computer programming only does one thing: It transforms one data set into another data set.  If we have fragments of the truth about the data, we are unlikely to give you anything more than fragments of an answer.
The output from this seems intuitively correct, but it would be better to know for sure that we had a representative test data set.

<?php // RAY_temp_hankknight.php
error_reporting(E_ALL);
echo '<pre>';

$arr = array
( 'xa0.txt'
, 'xa1.txt'
, 'xa10.txt'
, 'xa11.txt'
, 'xa12.txt'
, 'xa2.txt'
, 'xa3.txt'
, 'xa4.txt'
, 'xa5.txt'
, 'xa6.txt'
, 'xa7.txt'
, 'xa8.txt'
, 'xa9.txt'
)
;
natsort($arr);
print_r($arr);

$arr = array
( 'a/b/c_d-e555/xa0.txt'
, 'a/b/c_d-e555/xa1.txt'
, 'a/b/c_d-e555/xa10.txt'
, 'a/b/c_d-e555/xb10.txt'
, 'a/b/c_d-e555/xb11.txt'
, 'a/b/c_d-e555/xb2.txt'
, 'a/b/c_d-e555/xb1.txt'
, 'a/b/c_d-e555/xa11.txt'
, 'a/b/c_d-e555/xa12.txt'
, 'a/b/c_d-e555/xa2.txt'
, 'a/b/c_d-e555/xa3.txt'
, 'a/b/c_d-e555/xa4.txt'
, 'a/b/c_d-e555/xa5.txt'
, 'a/b/c_d-e555/xa6.txt'
, 'a/b/c_d-e555/xa7.txt'
, 'a/b/c_d-e555/xa8.txt'
, 'a/b/c_d-e555/xa9.txt'
)
;
natsort($arr);
print_r($arr);

Open in new window

HTH, ~Ray
ASKER CERTIFIED SOLUTION
Avatar of Ray Paseur
Ray Paseur
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of hankknight

ASKER

natsort() does exactly what I need!