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.

 

 

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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....

Link to comment
Share on other sites

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;
?>

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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)

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

<?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. >_<

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

$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

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • 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.