Jump to content

[SOLVED] extracting numbers, coverting, and replacing them in a string.


funsutton

Recommended Posts

I am having trouble with putting this together in my head.  Instead of explaining outright, I'm just going to give it to you by example.

 

$string = "Today the high is 72F and the low is 36F.  Tomorrow will be in the 60s."

 

I want to convert each number there to Celsius based on an indicator from the url.

 

I need to extract each number, convert each number, and replace each number back in the string.  I figure it's going to have extract into an array, and it will require regex to find the different numbers and account for the F and s  when searching.

 

I can handle the actual conversion to Celsius, however I am not sure how to extract and replace the numbers.

 

 

Ahem.

 

<?php
$string = "Today the high is 72F and the low is 36F.  Tomorrow will be in the 60s.";
$string = preg_replace('/\b(\d+)(\w)?\b/e', "round(($1 - 32) / 1. . (($2 == 's') ? 's' : (($2 == 'F') ? 'C' : ''))", $string);
echo $string;
?>

 

I could probably clean up the PHP part a bit, but it works.

wow man....you make that look really easy.  I would have never come up with that...at least like that.

 

now to figure out what you did :)

 

Thanks!

 

 

Ha, no problem.  If you want me to describe all the steps, I will.

If you would, that'd be awesome.  In the actual string I am using, it's more complicated in that it has brackets [], single quotes '....in fact, here's an example of the actual string.

 

mpdData['narr'].day['1']=new mpdNDObj(new Date('2008','7','30'),'1','A few isolated thunderstorms developing during the afternoon. High 86F. Winds light and variable. Chance of rain 30%.','Tomorrow');

mpdData['narr'].day['2']=new mpdNDObj(new Date('2008','7','30'),'1','Isolated thunderstorms in the evening. Fair skies overnight. Low 67F. Winds light and variable. Chance of rain 30%.','Tomorrow night');

mpdData['narr'].day['3']=new mpdNDObj(new Date('2008','7','31'),'2','Times of sun and clouds. Highs in the low 80s and lows in the mid 60s.','Sunday');

 

Not sure if this changes anything....but I have a feeling it will.  So far I haven't gotten any output....

You're right.  Fixed and tested:

 

<?php
$string = "mpdData['narr'].day['1']=new mpdNDObj(new Date('2008','7','30'),'1','A few isolated thunderstorms developing during the afternoon. High 86F. Winds light and variable. Chance of rain 30%.','Tomorrow');";
$string = preg_replace('/\b(\d+)([a-z]){1}\b/ei', "round(($1 - 32) / 1. . (($2 == 's') ? 's' : (($2 == 'F') ? 'C' : ''))", $string);
echo $string;
?>

Woops, forgot about that.  Here we go:

 

Regex: /\b(\d+)([a-z]){1}\b/ei

 

/ - opening delimeter

\b - non-word boundary.  This is to make sure that the numbers aren't inside of a word.

( - start of capture $1

\d - any digit from 0-9

+ - more than 1 (we don't want to capture 0 digits!)

) - end of capture $1

( - start of capture $2

[a-z] - any character from lowercase a through lowercase z

) - end of capture $2

{1} - capture one of the preceding token (we only want one character.  I could have left this out because it's automatically one, but whatever)

\b - non-word boundary.  We want to make sure there's no more characters or anything.

/ - ending delimeter

ei - Turns on "eval" mode and case-insensitivity.

Darkwater, some of your explanations is not quite correct...

 

Regex: /\b(\d+)([a-z]){1}\b/ei

 

/ - opening delimeter

\b - non-word boundary.  This is to make sure that the numbers aren't inside of a word.

( - start of capture $1

\d - any digit from 0-9

+ - more than 1 (we don't want to capture 0 digits!)

) - end of capture $1

( - start of capture $2

[a-z] - any character from lowercase a through lowercase z

) - end of capture $2

{1} - capture one of the preceding token (we only want one character.  I could have left this out because it's automatically one, but whatever)

\b - non-word boundary.  We want to make sure there's no more characters or anything.

/ - ending delimeter

ei - Turns on "eval" mode and case-insensitivity.

 

\b - non-word boundary.  This is to make sure that the numbers aren't inside of a word. (actually, this IS a word boundery.. a non word boundery is written as \B).

+ - more than 1 (we don't want to capture 0 digits!) (the plus means one or more.. not more than one.. a bit of a difference ;) ).

\b - non-word boundary.  We want to make sure there's no more characters or anything. (again, this does mean word boundery)

Yeah, I realized that I said "non-word boundary" after I could no longer edit the post. >_<  I know the difference, don't worry.  And with the + thing...I was just trying to explain it simply and wasn't really paying attention.  Good catches though.

<?php
$string = "mpdData['narr'].day['1']=new mpdNDObj(new Date('2008','7','30'),'1','A few isolated thunderstorms developing during the afternoon. High 86F. Winds light and variable. Chance of rain 30%.','Tomorrow');";
$string = preg_replace('/\b(-?[\d]+)([a-z]){1}\b/ei', "round(($1 - 32) / 1. . (($2 == 's') ? 's' : (($2 == 'F') ? 'C' : ''))", $string);
echo $string;
?>

 

Read your PM, try that.  Should work.

 

For anyone who wants to know, he asked about negative temps because it wasn't catching them.  This fixed it. >_<

Well, I was trying to use your code to do something a little different. I decided to make the phrase

 

"Tomorrow's high will be in the 36s"

 

to

 

"Tomorrow's high will be in the 30s"

 

So, my query looked like this:

$unit = "m";

$string = "mpdData['narr'].day['1']=new mpdNDObj(new Date('2008','7','30'),'1','A few isolated thunderstorms developing during the afternoon. High 86F. Winds light and variable. Chance of rain 30%.','Tomorrow hights will be in the 90s'');";

if ($unit == "m") {
$string = preg_replace('/\b(-?\d+)([a-z]){1}\b/ei', "round(($1 - 32) / 1. . (($2 == 's') ? 's' : (($2 == 'F') ? 'C' : ''))", $string);
$string = preg_replace('/\b(-?\d+)(s){1}\b/ei', "floor($1 * .1) * 10 . ($2 == 's') ? 's'", $string);
echo $string;
} else {
echo $string;
}

 

But, it's failing. Basically I am trying to round down to the nearest 10, the ones that have an "s" beside them, so that it makes more sense.

Actually, I do think this works....but it's converting all of the numbers.  I want it to only convert the one's with an s, not an F or C.

 

$string = preg_replace('/\b(\d+)(s){1}\b/ei', "floor($1 * .1) * 10 . (($2 == 's') ? 's' : '')", $string);

$string = preg_replace('/\b(\d+)s\b/ei', "floor($1 * .1) * 10 . 's'", $string);

 

Tested and it works with the code you just gave me.  It just so happens that 86F rounds to 30C exactly under normal circumstances, so I think that your one works too, but mine is a bit shorter.  I tried with different numbers to make sure it only worked on ones with 's' there.  :D

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.