note 83779 added to function.sprintf

From: Date: Wed, 11 Jun 2008 14:01:19 +0000
Subject: note 83779 added to function.sprintf
Groups: php.notes 
Request: Send a blank email to php-notes+get-140347@lists.php.net to get a copy of this message
I needed a piece of code similar to the one Matt posted below, on the 10th of March, 2008. However, I wasn't completely satisfied with Matt's code (sorry, Matt! No offense intended!), because 1) I don't like to initialize variables when it's not really needed, and 2) it contains two bugs. What are the bugs? First, Matt's code tests for count($vars) > 0, but if $var == "Hello world!", then count($var) == 1, but the foreach() will crash because $var has to be an array. So instead, my code tests for is_array($var). Second, if a key in $vars is a prefix of any of the later keys in the array (like 'object' is the beginning of 'objective') then the str_replace messes things up. This is no big deal if your keys are hard-coded and you can make sure the keys don't interfere, but in my code the keys are variable. So I decided to first sort the array on a decreasing length of the key. <?php function cmp($a, $b) { return strlen($b) - strlen($a); } function sprintf2($str, $vars, $char = '%') { if(is_array($vars)) { uksort($vars, "cmp"); foreach($vars as $k => $v) { $str = str_replace($char . $k, $v, $str); } } return $str; } echo sprintf2( 'Hello %your_name, my name is %my_name! I am %my_age, how old are you? I like %object and I want to %objective_in_life!' , array( 'your_name' => 'Matt' , 'my_name' => 'Jim' , 'my_age' => 'old' , 'object' => 'women' , 'objective_in_life' => 'write code' ) ); ?> If possible, and if you're willing, you can also embed the key fields in the text between percent-signs, rather than prefixing the keys with one. Sorting is no longer necessary, and the execution time is less than half of the code above: <?php function sprintf3($str, $vars, $char = '%') { $tmp = array(); foreach($vars as $k => $v) { $tmp[$char . $k . $char] = $v; } return str_replace(array_keys($tmp), array_values($tmp), $str); } echo sprintf3( 'Hello %your_name%, my name is %my_name%! I am %my_age%, how old are you? I like %object% and I want to %objective_in_life%!' , array( 'your_name' => 'Matt' , 'my_name' => 'Jim' , 'my_age' => 'old' , 'object' => 'women' , 'objective_in_life' => 'write code' ) ); ?> If you're willing to embed the keys in the text, you may also be willing to embed the keys themselves in percent signs, thus shaving off another 30% of the execution time: <?php function sprintf4($str, $vars) { return str_replace(array_keys($vars), array_values($vars), $str); } echo sprintf4( 'Hello %your_name%, my name is %my_name%! I am %my_age%, how old are you? I like %object% and I want to %objective_in_life%!' , array( '%your_name%' => 'Matt' , '%my_name%' => 'Jim' , '%my_age%' => 'old' , '%object%' => 'women' , '%objective_in_life%' => 'write code' ) ); ?> Of course, by now the sprintf function is no longer something you'd want to write to mum and dad about... ---- Server IP: 83.137.20.135 Probable Submitter: 24.132.252.217 ---- Manual Page -- http://www.php.net/manual/en/function.sprintf.php Edit -- https://master.php.net/note/edit/83779 Del: integrated -- https://master.php.net/note/delete/83779/integrated Del: useless -- https://master.php.net/note/delete/83779/useless Del: bad code -- https://master.php.net/note/delete/83779/bad+code Del: spam -- https://master.php.net/note/delete/83779/spam Del: non-english -- https://master.php.net/note/delete/83779/non-english Del: in docs -- https://master.php.net/note/delete/83779/in+docs Del: other reasons-- https://master.php.net/note/delete/83779 Reject -- https://master.php.net/note/reject/83779 Search -- https://master.php.net/manage/user-notes.php

« previous php.notes (#140347) next »