0

If I had a simple array where every value is a string, how would I be able to convert every value to the correct data-type? Example:

$array = array(
    "stringExample" => "string", 
    "floatExample" => "1.24", 
    "intExample" => "1", 
    "boolExample" => "TRUE"
);

Obviously, the float, integer and boolean are all strings since that's how they are put in the array. But I want the float to be an actual float, the integer to be an actual integer and so on. For small or fixed datasets, I could simply convert them one by one, but when dealing with large amounts of data and/or dynamic data, that would be impracticable. What is should have to be is:

$array = array(
    "stringExample" => "string", 
    "floatExample" => 1.24, 
    "intExample" => 1, 
    "boolExample" => true
);

The only other method I could think of is to make a loop that checks every value to see if it's a float, bool or else, but I feel like that's quite inefficient. Also because of the fact that it should only be converted if the value is ONLY a certain data-type. If the string was: "That's true", it should be a string, but if it's just "true", it should be a boolean. It also gets complicated with the 1 for example, since this can both be interpreted as a boolean and integer. But in my case, that should just be an integer and not a boolean.

Does someone have an efficient way to achieve this? Is it smart to do in the first place? Maybe some kind of array filter? Any help is appreciated!

6
  • 1
    Honestly, computers now are very fast, I would start with the for loop and convert them one by one. I wouldn't worry about it being inefficient until you really start to notice performance problems. This is especially true if you know what type each key is supposed to be. Like, would floatExample be known ahead of time to be a float, or would you need to test every value to guess what type it should be? If it's the former, and you know the type corresponding to each key, I'd just loop through it and not worry. Commented Oct 29, 2021 at 2:51
  • @404NotFound I guess you're right! The values are indeed known ahead of time, so it would be a simple case of converting. It would indeed be microseconds work, but I thought I remembered that there was some kind of filter that automatically converted values to the right data-type, but it's likely that I just misremembered. But in the case of non-static key-values, how do you think that I should approach that? Commented Oct 29, 2021 at 3:03
  • 1
    I'm not sure of any filter that would automatically convert the values, beyond PHP's type inference, but that's not literally changing the type. I don't know for sure what to do for non-static key-values, but my first thought would be to use filter_var or combinations of ctype_digit or is_int/is_numeric/is_string/etc and just loop over values. I would probably go from simpler types to complex, checking for bool, then int, then float, then string, etc, to hopefully reduce the chance you don't cast to the most appropriate type. Commented Oct 29, 2021 at 3:15
  • Why not just cast them when needed since you state you know their data-types in use? IE: (int) $array['intExample'] Commented Oct 29, 2021 at 3:22
  • @404NotFound filter_var was a really smart idea. I've created an foreach loop chat checks every value using FILTER_VALIDATE_INT, FILTER_VALIDATE_FLOAT and FILTER_VALIDATE_BOOL and it works like a charm. I didn't really realize that it's essentially just those 3 data-types that I needed. Commented Oct 29, 2021 at 3:23

1 Answer 1

3

There is one trick using the json_encode function with the JSON_NUMERIC_CHECK flag and then decode it back. But this affects all strings that look like numbers, so a string with the value "TRUE" will remain a string.

var_dump(json_decode(json_encode($array, JSON_NUMERIC_CHECK), true));
array(4) {
  ["stringExample"]=>
  string(6) "string"
  ["floatExample"]=>
  float(1.24)
  ["intExample"]=>
  int(1)
  ["boolExample"]=>
  string(4) "TRUE"
}

So you have to either iterate over the array with a checking values with the filter_var function:

array_walk_recursive($array, function(&$item){
    $filters = [FILTER_VALIDATE_INT, FILTER_VALIDATE_FLOAT, FILTER_VALIDATE_BOOLEAN];
    foreach($filters as $filter) {
        if (is_string($item)) {
            $item = filter_var($item, $filter, FILTER_NULL_ON_FAILURE) ?? $item;
            if (!is_string($item)) break;
        }
    }
});

demo

or try this:

array_walk_recursive($array, function(&$item){
    $item = json_decode(
        json_encode($item, JSON_PRESERVE_ZERO_FRACTION | JSON_NUMERIC_CHECK)
    );
    if (is_string($item)) {
        $item = filter_var($item, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) ?? $item;
    }
});

var_dump($array);

demo

There are differences in the results for integers with leading zeros.

Sign up to request clarification or add additional context in comments.

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.