3

As the title says, it's more out of interest really, I've got filenames in the format of 1347020478_Workbook1 12.19.19.csv - What I want to do is shift the timestamp off the start of the filename and return everything else, so Workbook1 12.19.19.csv

I've got the following code which works fine:

$original_filename = explode('_', $list->file);
$timestamp         = array_shift($original_filename);
$original_filename = implode('_', $original_filename);

As I say, the code above works but I wonder if there is a simpler way of doing so?

Levi Morrison
  • 19,116
  • 7
  • 65
  • 85
christian.thomas
  • 1,122
  • 1
  • 8
  • 19
  • `substr()`/`strpos()` and `strstr()` are two other simple ways, but they all take up so little in the way of resources that it's not something that you need to worry about. This is premature optimisation. Do it the way you feel most comfortable with/the way that seems most logical to you, and if it causes a bottleneck, then look at other ways of doing it (this applies to any given task your code performs). In the immortal words of Donald Knuth: "premature optimisation is the root of all evil". See also: http://www.codinghorror.com/blog/2009/01/the-sad-tragedy-of-micro-optimization-theater.html – DaveRandom Sep 07 '12 at 15:39
  • If you know your timestamp will always be a certain amount of characters (10 + 1 for the underscore), you could simple use: `file, 11); ?>` - That'll trim the string taking the timestamp and the underscore off. However, if your timestamp is going to vary in size, using a method below would best suit your needs. – James Sep 07 '12 at 15:54

6 Answers6

9

You could use a combination of stristr() and ltrim() to avoid generating arrays:

$original_filename = ltrim(stristr($list->file, '_'), '_');

See the manual: stristr returns all of haystack starting from and including the first occurrence of needle to the end.

jeroen
  • 91,079
  • 21
  • 114
  • 132
  • 2
    Since we are looking for an underscore [`strstr()`](http://php.net/manual/en/function.strstr.php) may be a better choice. – Florent Sep 07 '12 at 15:39
  • @Florent Good point, I used `stristr` out of habit but it should not make a difference. – jeroen Sep 07 '12 at 15:48
  • 1
    Nice guys, thanks very much for all the feedback - Accepted this solution, but there's some really decent others. – christian.thomas Sep 07 '12 at 16:04
5

You can use string functions such as strpos() and substr():

$original_filename = '1347020478_Workbook1 12.19.19.csv';
echo substr( $original_filename, strpos( $original_filename, '_') + 1);
Levi Morrison
  • 19,116
  • 7
  • 65
  • 85
piddl0r
  • 2,431
  • 2
  • 23
  • 35
4

If you know the length is fixed you can use substr. If not you can use strpos first. The following gives me 1-2 ms for the fixed-length "substr" method, 4ms for the "shift-implode" method, and 1-2 ms for the variable-length "substr" method. (It runs out of memory if I make the arrays bigger, but you get the idea.)

$loops=1000000;

$filename="1347020478_Workbook1 12.19.19.csv"; 
for ($i=0;$i<$loops;$i++){
    $fn[$i]=$filename;
}

$start1=time();
for ($i=0;$i<$loops;$i++){
    $newname=substr($fn[$i],11);    
}
$end1=time();
echo $newname." time=".($end1-$start1)."<br><br>";


$filename="1347020478_Workbook1 12.19.19.csv"; 
for ($i=0;$i<$loops;$i++){
    $fn[$i]=$filename;
}

$start1=time();
for ($i=0;$i<$loops;$i++){
    $original_filename  = explode('_', $fn[$i]);
    $timestamp          = array_shift($original_filename);
    $original_filename  = implode('_', $original_filename);    
}
$end1=time();
echo $original_filename." time=".($end1-$start1)."<br><br>";


$filename="1347020478_Workbook1 12.19.19.csv"; 
for ($i=0;$i<$loops;$i++){
    $fn[$i]=$filename;
}

$start1=time();
for ($i=0;$i<$loops;$i++){
    $st=strpos($fn[$i],"_");
    $newname=substr($fn[$i],$st+1);    
}
$end1=time();
echo $newname." time=".($end1-$start1);
Chuck P
  • 39
  • 4
  • +1 Nice one. You could reduce the number of loops and use `microtime` for more accuracy. And include `stristr` of course ;-) – jeroen Sep 07 '12 at 16:02
  • 1
    +1 for the crazy amount of effort even though 90 other answers were given. :) – Kristian Sep 07 '12 at 16:20
4

Abusing the fact that the timestamp will be fixed length for a long time, as long as all of your timestamps will fall between Sun, 09 Sep 2001 01:46:40 GMT and Sat, 20 Nov 2286 17:46:39 GMT, the simplest way is:

$original_filename = substr($list->file, 11);
Leigh
  • 12,859
  • 3
  • 39
  • 60
1

try:

preg_replace('/^[0-9]+_/', '', $filename);
Mike Brant
  • 70,514
  • 10
  • 99
  • 103
0

For your list of filenames, foreach of them, do a a preg_replace. Same result, 2 less steps.

Kristian
  • 21,204
  • 19
  • 101
  • 176
  • 2
    `Same result, 2 less steps` - and a lot more resource usage because you have to fire up PCRE every time. – DaveRandom Sep 07 '12 at 15:41
  • I'm not going to disagree with that, but in my defense, the OP did not ask for a higher performance solution, just a simpler one. – Kristian Sep 07 '12 at 16:19
  • I've just had a lengthy debate about exactly that and you are not wrong, which is why you don't get a downvote. But it doesn't get an upvote either because I just regard this whole question as moot point because it is optimising/simplifying/whatever that which does not need to be optimised/simplified/whatever. – DaveRandom Sep 07 '12 at 16:30
  • By the way I'm not a miserable/argumentative as I am coming across here, I seem to have got stuck on a soapbox about this particular question and I'm unable to get down. This is a reasonable answer to the question, it's the question itself I disagree with. If that makes any sense. – DaveRandom Sep 07 '12 at 20:34
  • lol believe me, as a professional developer, i've got to say this is hardly argumentative in comparison to what we normally deal with. you're totally A-OK in my book.. soap box and all haha – Kristian Sep 07 '12 at 20:50