Jump to content

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


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

Yeah, yours would have worked.  Good job. :D  But uhh, I'd still use mine because I got rid of the ternary operator in the PHP part because it's not necessary if you KNOW it's going to be an S anyway.

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.