tags:

views:

361

answers:

5

I would like to convert a string into floating numbers. For example

152.15 x 12.34 x 11mm

into

152.15, 12.34 and 11

and store in an array such that $dim[0]=152.15, $dim[1]=12.34, $dim[2]=11.

I would also need to handle things like

152.15x12.34x11 mm

152.15mmx12.34mm x 11mm

Thank you.

+5  A: 
$str = '152.15 x 12.34 x 11mm';
preg_match_all('!\d+(?:\.\d+)?!', $str, $matches);
$floats = array_map('floatval', $matches[0]);
print_r($floats);

The (?:...) regular expression construction is what's called a non-capturing group. What that means is that chunk isn't separately returned in part of the $mathces array. This isn't strictly necessary in this case but is a useful construction to know.

Note: calling floatval() on the elements isn't strictly necessary either as PHP will generally juggle the types correctly if you try and use them in an arithmetic operation or similar. It doesn't hurt though, particularly for only being a one liner.

cletus
You can ditch the outer parentheses, and then $matches[0] will contain the matches. Also, what's the purpose of `?:` ?
troelskn
You're quite right about the outer parentheses. Changed that. ?: makes whats inside those parentheses as a non-capturing group, meaning it wont separately be put in the $matches array anywhere, which it would be if you didnt include it. Not strictly necessary but cleaner and in more complicated examples may be necessary.
cletus
@cletus: You're absolutely right about the non-capturing parenthesis, but it makes the regex way less readable imo. I "get" Paolo's regex much faster then yours.
soulmerge
Well, look on the bright side: you learnt something extra. :) Non-capturing groups are useful.
cletus
Also, I read mine and its clear that I'm not interested in separately capturing parts of the number, just the whole number. The above clearly matches your intent, which is what you should be striving for imho.
cletus
It might be useful to also cast $matches[0] results as (float)
Ambirex
Thanks for the explanation, cletus. For some reason, I didn't know about non-capturing groups. Now I do.
troelskn
Thanks for the answer, that's worked well.
Tian Bo
+1  A: 
$str = "152.15 x 12.34 x 11mm";
$str = str_replace("mm", "", $str);
$str = explode("x", $str);
print_r($str); // Array ( [0] => 152.15 [1] => 12.34 [2] => 11 )

Tested it and it works on all strings above.

Ólafur Waage
+2  A: 
$string = '152.15 x 12.34 x 11mm';
preg_match_all('/(\d+(\.\d+)?)/', $string, $matches);
print_r($matches[0]); // Array ( [0] => 152.15 [1] => 12.34 [2] => 11 )
Paolo Bergantino
+1  A: 
<?php

$s = "152.15 x 12.34 x 11mm";

if (preg_match_all('/\d+(\.\d+)?/', $s, $matches)) {
    $dim = $matches[0];
}

print_r($dim);

?>

gives

Array
(
    [0] => 152.15
    [1] => 12.34
    [2] => 11
)
動靜能量
Why not $dim = $matches[0]?
soulmerge
that's true... corrected. at first i was printing out each value. if $dim already has some values, we either use a loop or array_merge()
動靜能量
Good one, +1 for me
SleepyCod
A: 
preg_match_all("/\d*\.?\d+|\d+/", "152.15mmx12.34mm x .11mm", $matches);

This example supports numbers like .11 as well, since they are valid numbers. $matches[0] will contain 152.15, 12.34 and 0.11, given that you type cast the result to float. If you don't 0.11 will appear as .11. I would type cast using array_map.

$values = array_map("floatval", $matches[0]);

You can use the values for anything math without type casting them though. casting is just needed when printing them directly.

antennen
Your example would be clearer if you used the sample data from the question.
Toby Allen
This should make it clearer.
antennen