0

If I have two strings in an array:

$x = array("int(100)", "float(2.1)");

is there a simple way of reading each value as the number stored inside as a number?

The reason is I am looking at a function (not mine) that sometimes receives an int and sometimes a float. I cannot control the data it receives.

function convertAlpha($AlphaValue) { 
    return((127/100)*(100-$AlphaValue));
}

It causes an error in php

PHP Notice: A non well formed numeric value encountered

which I want to get rid of.

I could strip the string down and see what it is and do an intval/floatval but wondered if there was a neat way.

UPDATE:

Playing about a bit I have this:

function convertAlpha($AlphaValue) {

$x = explode("(", $AlphaValue);
$y = explode(")", $x[1]);

if ($x[0] == "int") {
    $z = intval($y[0]);
}

if ($x[0] == "float") {
    $z = floatval($y[0]);
}

return((127/100)*(100-$z)); }

This which works but it just messy.

11
  • Can you change this int(100) format you're passing? Commented Aug 20, 2018 at 19:51
  • Your input strings look like the output of var_dump(). var_dump() is meant to be used for debugging, its output is not suitable to be saved/transmitted and parsed to restore the original data structures. Use json_encode() for this purpose. Commented Aug 20, 2018 at 19:51
  • 1
    This sounds a bit like an XY Problem. Where is your array of initial data coming from? There might be another way of natively parsing it without resorting to manual string manipulation. Commented Aug 20, 2018 at 19:51
  • 1
    Why are you putting int() and float() around the numbers in the first place? If you just have $a = array("100", "2.1"); PHP will automatically convert them to the appropriate numeric types when you use them in arithmetic expressions. Commented Aug 20, 2018 at 19:55
  • Why not using is_numeric before deciding if return the math operation or false? Commented Aug 20, 2018 at 19:55

4 Answers 4

3
<?php

$x = array("int(100)", "float(2.1)");

$result = [];

foreach($x as $each_value){
    $matches = [];
    if(preg_match('/^([a-z]+)(\((\d+(\.\d+)?)\))$/',$each_value,$matches)){
        switch($matches[1]){
          case "int": $result[] = intval($matches[3]); break;
          case "float": $result[] = floatval($matches[3]);
        }
    }
}

print_r($result);

OUTPUT

Array
(
    [0] => 100
    [1] => 2.1
)
Sign up to request clarification or add additional context in comments.

1 Comment

@RGriffiths Glad to help :)
0

The simplest would simply be to make the array as you need it, so instead of

$x = array("int(100)", "float(2.1)");

you have:

$x = [100, 2.1];

but as this is not what you want you got two choices now. One, is to use eval(), for example:

$x = ['(int)100', '(float)2.1'];
foreach ($x as $v) {
    var_dump(eval("return ${v};"));
}

which will produce:

int(100)
double(2.1)

As you noticed, source array is bit different because as there is no such function in PHP as int() or float(), so if you decide to use eval() you need to change the string to be valid PHP code with the casting as shown in above example, or with use of existing intval() or floatval() functions. Finally, you can parse strings yourself (most likely with preg_match()), check for your own syntax and either convert to PHP to eval() it or just process it in your own code, which usually is recommended over using eval().

6 Comments

It would be great for the array to be as you suggest but it is dynamic depending on chart data. therefore I cannot change what is parsed to the function,
then as I said - you need to either parse it yourself or convert to valid PHP code (which also means -> parse it yourself, so you know...) and then eval().
This approach is REALLY dangerous--using eval() on untrusted incoming data is a major security issue. eval() should NOT be used for something as simple as parsing a number out of a string.
who told it's unsafe or user provided? who told that you cannot do multiple checks prior calling eval(). All this "eval() is bad, blah blah" rant is pure BS. If you know what it does and take precautions is as useful as any other PHP method available. and as I mentioned in my answer - OP still would need to do some manual processing, so eval() is no beneficial here really. But it's his choice.
@MarcinOrlowski of course you can take precautions to make eval() safe. But you didn't include these in your answer or mention them, and there's no reason to assume that the OP knows to implement them. Additionally, I think eval() is just plain overkill for something that can be done using regex (like @vivek_23's answer). If you don't have to use eval(), don't.
|
0

The way I would do it is by using a regex to determine the type and value by 2 seperate groups:

([a-z]+)\((\d*\.?\d*)\)

The regex captures the alphanumeric characters up and until the first (. It then looks for the characters between the ( and ) with this part: \d*\.?\d*.

The digit-part of the regex accepts input like: 12.34, .12, 12. and 123

$re = '/([a-z]+)\((\d*\.?\d*)\)/m';
$input_values = array('int(100)', 'float(2.1)');

foreach($input_values as $input) {
    preg_match_all($re, $input, $matches, PREG_SET_ORDER, 0);
    var_dump($matches);
}

Which leads to the output below. As you can see, there is the type in the [1] slot and the number in the [2] slot of the array

array(1) {
  [0]=>
  array(3) {
    [0]=>
    string(8) "int(100)"
    [1]=>
    string(3) "int"
    [2]=>
    string(3) "100"
  }
}
array(1) {
  [0]=>
  array(3) {
    [0]=>
    string(10) "float(2.1)"
    [1]=>
    string(5) "float"
    [2]=>
    string(3) "2.1"
  }
}

You can then use a check to perform the casting like:

$value;
if(matches[1] === "int") {
    $value = intval($matches[2]);
} elseif (matches[1] === "float") {
    $value = floatval($matches[2]);
}

The latter code still needs error handling, but you get the idea. Hope this helps!

Comments

0

PHP is historically typed against strings so it's pretty strong with cases like these.

$x = array("int(100)", "float(2.1)");
                ^^^           ^^^

You can actually turn each of those strings into a number by multiplying the substring starting after the first "(" with just one to turn it into a number - be it integer or float:

$numbers = array_map(function($string) {
    return 1 * substr(strstr($string, '('), 1);
}, $x);

var_dump($numbers);

array(2) {
  [0] =>
  int(100)
  [1] =>
  double(2.1)
}

That is PHP takes everthing numberish from a string until that string seems to end and will calculate it into either an integer or float (var_dump() shows float as double). It's just consuming all number parts from the beginning of the string.

Not saying existing answers are wrong per-se, but if you ask that as a PHP question, PHP has a parser very well for that. My suggestion is to just remove the superfluous information from the beginning of the string and let PHP do the rest.

If you want it more precise, regular expressions are most likely your friend as in the yet top rated answer, still combined with PHP will give you full checks on each string:

$numbers = array_map(function($string) {
    $result = preg_match('~^(?:int|float)\(([^)]+)\)$~', $string, $group) ? $group[1] : null;
    return null === $result ? $result : 1 * $result;
}, $x);

So all non int and float strings will be turned into NULLs (if any).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.