tags:

views:

171

answers:

7

I've seen so many misuses of RegExp, I don't really like it :)

I have string (as a result of two str_replaces) that might look something like this:

.?This iš my ".stRiNg."!
          |
          V
--this-is-my---string---

Is there any way better than

$string = trim(preg_replace('/[-]+/u','-', $string),'-');

to get:

this-is-my-string

?

+5  A: 

I don't understand why you are looking for a 'better' way. Your way uses a simple regex in a place where it's perfectly appropriate to do so. What could be better than that?

GSto
Not everyone prefer regular expressions. I admit they are really cool in some situations, but the code looks ugly and if you want to do something easy and want to have your code clean, it's better to use other options. But it's matter of opinion.
Ondrej Slinták
@Ondrej yes, there a lot of times when people use regular expression when they aren't applicable, But there are a plenty of times when they are best the tool for the job. RegExes are for manipulating patterns in strings, which is exactly what the OP wants to accomplish. @stereofrog and @Austin stated it well in there comments.
GSto
@GSto: I think you're right :) I just wasn't sure it's perfectly appropriate, not even appropriate actually.
Adam Kiss
A: 
$parts = explode("-",'--this-is-my---string---');
for($i=0;$i<count($parts);$i++) {
    if (strlen($parts[$i]) < 1) {
        unset($parts[$i]);
    }
}
reset($parts);
$string = implode("-",$parts);
Brant
+3  A: 
print implode('-', array_filter( explode( '-', $string) ) );

Easy. :)

toscho
@toscho, nice. I didn't know the callback was optional in `array_filter` :)
macek
+1 for elegance
Manos Dilaverakis
+1  A: 

A better way? Probably not. Another way? Yes (essentially one-line version of Brant's answer):

implode('-', array_filter(explode('-', $string), function($s) { return strlen($s); }));

Note that you can't just use the naked array_filter reliably, because !!"0" == false in PHP.

vicvicvic
@vicvicvic, you can use `array_filter` naked because `'' == false`.
macek
Yes, but `"0" == false` as well. Thus, a string like "0-is--zero" becomes "is-zero".
vicvicvic
A: 

So you want to go from

--this-is-my---string---

to

this-is-my-string?

The best way would be a reg exp, but if you want a simple solution in php you can use

$string = "--this-is-my---string---";
while (! strpos($string, "--") === false) {
  $string = str_replace("--", "-", $string);
}

After the loop $string will contain the result.

murze
@murze, you should test you code. It doesn't work. I think you were meaning to use `strpos($string, "--") !== false` for your `while` condition. Also, this doesn't clean the `-` off the beginning and end of the string.
macek
+6  A: 

preg_replace() wins

<?php

function benchmark($callback){
  echo sprintf('%-30s: ', $callback);
  $t = microtime(true);
  foreach(range(1, 10000) as $n){
    call_user_func($callback);
  }
  echo (microtime(true)-$t)."\n";
}

function implode_explode_filter(){
  implode('-', array_filter(explode('-', '--this-is-my---string---')));
}

function preg_replace_trim(){
  preg_replace('/-+/', '-', trim('--this-is-my---string---', '-'));
}

function brant(){
  $parts = explode("-",'--this-is-my---string---');
  for($i=0;$i<count($parts);$i++) {
      if (strlen($parts[$i]) < 1) {
          unset($parts[$i]);
      }
  }
  reset($parts);
  $string = implode("-",$parts);
}

function murze_bisko(){
  $string = "--this-is-my---string---";
  while (strpos($string, "--") !== false) {
    $string = str_replace("--", "-", $string);
  }
  $string = trim($string, '-'); # both of their answers were broken until I added this line
}

benchmark('implode_explode_filter');
benchmark('preg_replace_trim');
benchmark('brant');
benchmark('murze_bisko');

# Output
# implode_explode_filter        : 0.062376976013184
# preg_replace_trim             : 0.038193941116333
# brant                         : 0.11686086654663
# murze_bisko                   : 0.058025121688843
?>
macek
Thank you! (15++)
Adam Kiss
As Adam states "I don't really like it". Sometimes the performance difference is minor that is unless the traffic is just crazy.
Brant
@Adam Kiss, perhaps you would like to update your name to Adam Kkiss :)
macek
@Brant... yeah well... I'v seen different options. :D
Adam Kiss
@Adam, No prob glad you found your answer.
Brant
@smotchkkiss - I would say you put my solution in the wrong place :) I don't test if the -- is in the string, i just replace. Trying to strpos makes additional loops on the string which makes it slower!
bisko
@bisko, you should test your code. `str_replace('--','-', '---')` will result in `--` (not `-` like you might be assuming). I grouped your answer with @murze's because your solution alone doesn't work :)
macek
@smotchkkiss that's why I call str_replace('--','-'..) twice, not only once like you show in your comment :)
bisko
@bisko, I'm sure the OP has a dynamic string though. Meaning, there's a chance that more than 3 `-` could show up. This needs to be accounted for.
macek
@smotchkkiss that's what I'm trying to explain - it doesn't matter what the string is or how many '-' it has. Running replacement of -- with - twice makes sure that only single - remain! Try it with any string you like and you would see I'm right :) So trim(str_replace('--', '-', str_replace('--', '-', $dynamic_string)),'-'); would give just the wanted result... and it's the fastest way :)
bisko
A: 

Just for the sake of the competition:

$string = str_replace('--','-', str_replace('--','-', '--this-is-my---string---'));

This is the fastest way to do it. It first replaces double -- with single and then cleans the rest again, so only single - remain.

bisko
@bisko, how do you suggest testing to see if anymore `--` exist? And what about cleaning the `-` off the beginning and end of the string?
macek
No testing is needed, this removes all double, triple or more dashes. to remove the first and last - trim ($string,'-');
bisko