1

It feels like that problem has already been solved but my search did not find a "good" solution. I have a time critical app and need to convert a typical string into an assoc array:

"appliCAation=webCALL&Arg1=ABC&arG2=xyZ&someMore=Dec-1950"

I know I can use parse_str() for that but I would like to "normalize" the user input so that all keys are always uppercase and all values are always lowercase (and vice versa, if possible done by parameter and NOT widen the footprint of the code).

Since array_change_key_case() does not work recursively, I search for an elegant way with few lines of code and efficient performance.

At the moment I use parse_str( strtolower( $input ), $arr ); and then loop (recursively) the array to change the keys. Unfortunately that needs two methods and "many" code lines.

Any faster / better / smaller solution for that?

3
  • Once the problem is broken down ("parse first"), it's easy to find solutions relating to each task: array_change_key_case , stackoverflow.com/q/25068571/2864740 , etc. Commented May 23, 2020 at 17:46
  • Oh, I see.. some upper and some lower.. :| Commented May 23, 2020 at 17:54
  • 1
    You mention recursively twice but haven't shown an array that would need to be recursed. Commented May 23, 2020 at 17:55

1 Answer 1

1

Flip your logic and uppercase everything and then recursively lower case the values:

parse_str(strtoupper($string), $array);    
array_walk_recursive($array, function(&$v, $k) { $v = strtolower($v); });

This will work for multiple dimensions such as:

$string = "appliCAation=webCALL&Arg1=ABC&arG2=xyZ&someMore=Dec-1950&a[yZ][zzz]=efG";

Yielding:

Array
(
    [APPLICAATION] => webcall
    [ARG1] => abc
    [ARG2] => xyz
    [SOMEMORE] => dec-1950
    [A] => Array
        (
            [YZ] => Array
                (
                    [ZZZ] => efg
                )
        )
)

After rereading the question I see you want to be able to change or control whether the keys and values are uppercase or lowercase. You can use() a parameters array to use as function names:

$params = ['key' => 'strtoupper', 'val' => 'strtolower'];
parse_str($params['key']($string), $array);    
array_walk_recursive($array, function(&$v, $k) use($params){ $v = $params['val']($v); });

To change just the keys, I would use a Regular Expression on the original string:

$keys = 'strtoupper';
$string = preg_replace_callback('/[^=&]*=/', function($m) use($keys) { return $keys($m[0]); }, $string);
parse_str($string, $array);

[^=&]*= is a character class [] matching characters that are ^ not = or & 0 or more times * followed by =.

And finally, here is one that will do keys and values if you supply a function name (notice val is empty), if not then it is not transformed:

$params = ['key' => 'strtoupper', 'val' => ''];
$string = preg_replace_callback('/([^=&]*)=([^=&]*)/',
                                function($m) use($params) {
                                    return (empty($params['key']) ? $m[1] : $params['key']($m[1]))
                                           .'='.
                                           (empty($params['val']) ? $m[2] : $params['val']($m[2]));
                                }, $string);
parse_str($string, $array);
Sign up to request clarification or add additional context in comments.

4 Comments

one last question ... any possibility to keep the values "as is" as an "alternative"? I understand that the first step is to change the whole string to what the keys should look like and then use array_walk to "correct" the values. What If I would NOT want to alter the values and only alter the keys?
Edited with a regex.
NP, added another one ;-)
wow. thanks. great work. I need to deal with / learn regex more intensively!

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.