What general tips do you have for golfing in PHP? I'm looking for ideas that can be applied to code golf problems in general that are at least somewhat specific to PHP (e.g. "remove comments" is not an answer). Please post one tip per answer.
-
\$\begingroup\$ Wait, am I doing it right?... Anyway, I'm really curious about this one. PHP is used by many people and golfers, but I almost have no idea how to golf a PHP code. \$\endgroup\$– JiminPCommented Jun 20, 2011 at 14:11
-
\$\begingroup\$ Use short tags <??> It can save a few bytes. \$\endgroup\$– MobCommented Aug 12, 2011 at 20:49
-
\$\begingroup\$ This is added in PHP 8.4: wiki.php.net/rfc/new_without_parentheses \$\endgroup\$– mbomb007Commented Nov 21 at 21:23
40 Answers
Understand how variables and whitespace interact with PHP's language constructs.
In my (admittedly short) time golfing, I have found that PHP's language constructs (e.g. echo, return, for, while, etc) behave in a less-than-intuitive way when interacting with variables and whitespace.
echo$v;
, for example, is perfectly valid, as are return$v;
and other similar constructs. These small reductions in whitespace can lead to a significant cumulative decrease in length.
Keep in mind, though, that variables before language constructs require a space after, as in the following example:
foreach($a AS$b){}
Because AS
is a language construct, a space is not required before the variable $b
, but if one were to omit the space before it, resulting in $aAS
, this would be parsed as a variable name and lead to a syntax error.
-
6\$\begingroup\$
foreach($a[1]as$b)
needs no white space. This is not about language constructs and variables, but about spaces between word-characters of different words. \$\endgroup\$– TitusCommented Jul 22, 2016 at 19:05 -
1\$\begingroup\$ Another instance where you need whitespace is in string concatenation. For instance,
echo $a+5." text"
will not work because PHP thinks the.
is a decimal point for the5
. To make it work, you would need to add a space like this:echo $a+5 ." text"
\$\endgroup\$ Commented Aug 16, 2016 at 14:47 -
\$\begingroup\$ @BasicSunset That statement can be written as
echo$a+5," text";
. Theecho
construct allows you to pass multiple parameters. where one would have to writeecho"result: ".($a+5)."!";
, you can writeecho"result: ",$a+5,"!";
. In fact, passing multiple parameters to anecho
is a micro-optimization, since the code will run a tiny bit faster (since you don't concatenate the output, but send it separately). For challenges about writting the fastest code, this may help a tiny tiny tiny bit. \$\endgroup\$ Commented Apr 7, 2017 at 7:59 -
\$\begingroup\$ @IsmaelMiguel It works with
echo
, but not withprint
(which you need if you put it inside an expression:echo
is a pure construct with no return value whileprint
can act as a function: it requires no parentheses, but it always returnsint(1)
. \$\endgroup\$– TitusCommented Oct 10, 2017 at 8:00 -
\$\begingroup\$ @Titus I didn't said anything about
print
. \$\endgroup\$ Commented Oct 11, 2017 at 13:49
Use strings wisely.
This answer is two-fold. The first part is that when declaring strings, you can utilize PHP's implicit conversion of unknown constants to strings to save space, e.g:
@$s=string;
The @
is necessary to override the warnings this will produce. Overall, you end up with a one-character reduction.
is that sometimes, it may be space effective to set a variable to the name of an often used function. Normally, you might have:
preg_match(..);preg_match(..);
But when golfing, this can be shortened easily to:
@$p=preg_match;$p(..);$p(..);
With only two instances of "preg_match", you're only saving a single character, but the more you use a function, the more space you will save.
-
11\$\begingroup\$ @ is not needed in codegolf; notices and warnings (including
E_DEPRECATED
) are acceptable \$\endgroup\$– TitusCommented Jul 22, 2016 at 19:13 -
3\$\begingroup\$ @Titus But in PHP, the warnings would output to the standard file output, so they are needed. \$\endgroup\$ Commented Dec 1, 2016 at 2:16
-
1\$\begingroup\$ @Titus I believe you can suppress them in the
php.ini
file \$\endgroup\$ Commented Mar 6, 2018 at 15:24 -
\$\begingroup\$ Does the string tip work for empty strings? e.g.
@$k=;
\$\endgroup\$ Commented Feb 2, 2021 at 10:08 -
\$\begingroup\$ Starting from PHP 8, an undefined constant causes Error to be thrown. \$\endgroup\$ Commented Oct 14, 2021 at 20:55
You don't always need to write out conditional checks. For example, some frameworks use this at the top of their files to block access:
<?php defined('BASE_PATH')||die('not allowed');
Or in normal functions
$value && run_this();
instead of
if($value) { run_this(); }
Use short array syntax
Since PHP 5.4, arrays can be declared using square brackets (just like JavaScript) instead of the array()
function:
$arr=['foo','bar','baz'];
// instead of
$arr=array('foo','bar','baz');
It will save five bytes.
But It may cost bytes if you have "holes" in an associative array:
$arr=array(,1,,3,,5);
// is one byte shorter than
$arr=[1=>1,3=>3,5=>5];
the disadvantage hits a little later if you can fill the holes with "empty" values:
// saves two bytes over array()
$arr=[0,1,0,3,0,5];
// but for a larger array
$arr=[0,1,0,3,0,5,0,7,0,9,0,11];
// costs two byte more than
$arr=array(,1,,3,,5,,7,,9,,11);
-
3\$\begingroup\$ PHP 7.1 also introduced short list assignment:
[,$a,$b,$c]=$argv;
. \$\endgroup\$– TitusCommented May 19, 2017 at 0:12
Use ${0}, ${1}, ${2}, ... instead of $a[0], $a[1], $a[2], ...
Unless you're performing an array manipulation, most references to an array index $a[$i]
can be replaced with simply $$i
. This is even true if the index is an integer, as integers are valid variable names in PHP (although literals will require brackets, e.g. ${0}
).
Consider the following implementation of the Rabonowitz Wagon spigot:
3.<?for(;$g?$d=0|($a[$g]=$d*$g--/2+($a[$g]?:2)%$g*1e4)/$g--:238<<printf($e?'%04d':'',$e+$d/$g=1e4)^$e=$d%$g;);
This can be improved by 6 bytes, simply by replacing both array references $a[$g]
with $$g
instead:
3.<?for(;$g?$d=0|($$g=$d*$g--/2+($$g?:2)%$g*1e4)/$g--:238<<printf($e?'%04d':'',$e+$d/$g=1e4)^$e=$d%$g;);
-
2
Learn a large subset of the library functions.
PHP's library is pretty huge and provides a ton of convenient functions that can greatly shorten various tasks. You could just search every time you try to do something, but beyond wasting time you might not find anything that matches your particular search. The best way is just to get familiar with the library and memorize function names and what they do.
-
7\$\begingroup\$ That's a lot of memorization, especially given the rather inconsistent naming of a whole lot of functions ;-) \$\endgroup\$– JoeyCommented Jun 24, 2011 at 20:49
-
\$\begingroup\$ @Joey Agreed. Akin to memorizing the Java library, except that would be arguably less useful since it's more verbose. \$\endgroup\$ Commented Jun 24, 2011 at 20:54
-
3\$\begingroup\$ I find that the most important functions for the challenges I've come across so far here are the string manipulation and array manipulation functions. Creative use of those can really cut down the code. \$\endgroup\$– migimaruCommented Aug 12, 2011 at 17:03
-
\$\begingroup\$ Creativity required - there's a bunch of stuff that is very niche, and some stuff that would be useful + should exist but doesn't. Like getting an individual char of a string. \$\endgroup\$ Commented Feb 2, 2021 at 10:11
Running functions inside strings.
Try this:
$a='strlen';
echo "This text has {$a('15')} chars";
Or try this:
//only php>=5.3
$if=function($c,$t,$f){return$c?$t:$f;};
echo <<<HEREDOCS
Heredocs can{$if(true,' be','not be')} used too and can{$if(<<<BE
{$if(true,1,0)}
BE
,'','not')} be nested
HEREDOCS;
//Expected output: Heredocs can be used too and can be nested
This only works with strings using ""
and heredocs (DON'T make confusion with nowdocs).
Using nested functions is only possible inside nested heredocs (or you will run into parse errors)!
-
\$\begingroup\$
you will run into parse errors
I cant read it myself? How does the pesky Zend engine put this together \$\endgroup\$ Commented Mar 6, 2018 at 19:45 -
\$\begingroup\$ The next time I'm in a "PHP is a good programming language" argument, I'm going to use this as a counter-point. Wow. \$\endgroup\$– primoCommented Apr 26, 2018 at 9:11
-
\$\begingroup\$ @primo Is it that bad? :O \$\endgroup\$ Commented Apr 27, 2018 at 11:01
looping through strings
can be done with 26 bytes or with 24 down to 18:
foreach(str_split($s)as$c) # A) 26 - general
for($p=0;a&$c=$s[$p++];) # B) 24 - general
for($p=0;$c=$s[$p++];) # C) 22 - if $s has no `0` character
for(;a&$c=$s[$p++];) # D) 20 - if $p is already NULL or 0 (does NOT work for false)
for(;$c=$s[$p++];) # E) 18 - both C and D
for(;$o=ord($s[$p++]);) # F) 23 - work on ASCII codes, if $s has no NULL byte and D
for(;~$c=$s[$p++];) # G) 19 - if $s has no chr(207) and D
$a&$b
does a bitwise AND on the (ascii codes of) the characters in $a
and $b
and results in a string that has the same length as the shorter of $a
and $b
.
-
\$\begingroup\$ can you please add
ord($s[$p++])
as alternativefor(;$s+=ord($argv[++$i])%32?:die($s==100););
againstfor(;$c=$argv[++$i];)$s+=ord($c)%32;echo$s==100;
in this question codegolf.stackexchange.com/questions/116933/… \$\endgroup\$ Commented Apr 19, 2017 at 10:41 -
\$\begingroup\$ Please add
~
for cases you are working only with digits \$\endgroup\$ Commented Apr 30, 2017 at 21:13 -
\$\begingroup\$ Note that PHP 7.2 yields warnings for the
~$c
approach. \$\endgroup\$– TitusCommented Feb 22, 2019 at 15:13
by any other name ... function aliases
use ...
join
instead ofimplode
chop
instead ofrtrim
(chop
in PERL is different!)die
instead ofexit
fputs
instead offwrite
is_int
instead ofis_integer
oris_long
is_real
instead ofis_float
oris_double
key_exists
instead ofarray_key_exists
mysql
instead ofmysql_db_query
... to name the most important aliases. Take a look at http://php.net/aliases for more.
-
\$\begingroup\$ Oh ... and did You know that
die
works with and without parameters?die(1)
will exit the program with error code1
(not completely sure on this; needs testing);die
will exit with code0
, anddie("Hello")
will exit with code0
after printingHello
. \$\endgroup\$– TitusCommented Mar 9, 2017 at 17:04
fun with typecasts
!!$foo
will turn any truthy value totrue
(or1
in output), falsy values (0, empty string, empty array) tofalse
(or empty output)
This will rarely be needed in code golf, for in most cases where you need a boolean, there is an implicit cast anyway.(int)$foo
can be written as$foo|0
orfoo^0
, but may need parentheses.
For booleans and strings,$foo*1
or+$foo
can be used to cast to int.Unlike most other languages, PHP handles strings with numeric values as numbers. So if you have any string that contains a number you have to calculate with, just calculate.
The other way does not work: To multiply any number in a variable with
10
, you could append a zero:*10
->.0
. But in this case, PHP will take the dot as decimal point and complain. (It´s different though if you have a variable amount of zeroes in a string.)To turn an array into a string, use
join
instead ofimplode
.
If you don´t need a delimiter, don´t use it:join($a)
does the same asjoin('',$a)
Incrementing strings: The most amazing feature imo is that
$s=a;$s++;
produces$s=b;
. This works with uppercase and lowercase characters.$s=Z;$s++;
results in$s=AA;
.
This also works with mixed case:aZ
tobA
,A1
toA2
,A9
toB0
andz99Z
toaa00A
.
Decrement does not work on strings. (And it does not onNULL
).
Back in PHP 3,$n="001";$n++;
produced$n="002";
. I am a little sad they removed that.
Whatever you golf: always have the operator precedence table at hand.
Use shorttags
In normal code, it's good practice to use <?php
and ?>
. However, this is not normal code - you are writing a code golf code. Instead of <?php
, write <?
. Instead of <?php echo
, write <?=
. Don't type ?>
at end - it's completely optional. If you need ?>
for some reason (for example to output text, and it's shorter somehow, or something, don't put a semicolon before it - it's not needed, as ?>
implies semicolon.
Wrong (definitely too long):
<?php echo ucfirst(trim(fgets(STDIN)));?>s!
Correct:
<?=ucfirst(trim(fgets(STDIN)))?>s!
-
\$\begingroup\$ With the
-r
flag (which comes free), you don´t even any tags at all (and you´re not allowed to use any). \$\endgroup\$– TitusCommented Feb 22, 2019 at 15:12
array_flip vs array_search
use
array_flip($array)[$value]
instead of
array_search($value,$array)
to save 1 Byte in arrays where the occurence of each value is unique
some interesting facts on variable variables
I just had to share them (even before I verified that at least one of them helps golfing):
- Use letters:
$x=a;$$x=1;$x++;$$x=2;echo"$a,$b";
prints1,2
but other arithmetic operations do not work with letters. - As primo mentioned earlier, you can use pure numbers as variable names:
$a=1;$$a=5;$a++;$$a=4;${++$a}=3;echo${1},${2},${3};
prints543
. - You can not only use
[0-9a-zA-Z_]
for variable names, but EVERY string:
$x="Hello!";$$x="Goodbye.";echo${"Hello!"};
printsGoodbye.
. - But: Everything but
[a-zA-Z_][a-zA-Z_0-9]*
as variable names requires braces for literal use. - With no variables defined,
$$x=1
sets${NULL}
, which is the same as${false}
and${""}
. $a=1;$$a=5;
does not only set${1}
, but also${true}
.one more, the weirdest one I´ve found so far: Try
$a=[];$$a=3;echo${[]};
. Yes, it prints3
!
The reason for most of this: variable names are always evaluated to strings.
(Thanks @Christoph for pointing out.)
So, whatever you get when you print
or echo
the expression, that´s what you get as variable name.
-
2\$\begingroup\$ Variable names are converted to strings that explains the last three points on your list.
[]
converts toArray
:${[]} = 5;echo $Array;
prints5
. I'm pretty sure you know that but it might not be obvious to everyone :) \$\endgroup\$ Commented Mar 15, 2017 at 9:16 -
\$\begingroup\$ @Jeff I fixed the typo. Thanks for noticing. \$\endgroup\$– TitusCommented Oct 11, 2017 at 11:44
Use ternary operators
if(a==2){some code;}else{some other code;}
can be abbreviated to this:
(a==2?some code:some other code);
Shorter, huh?
-
\$\begingroup\$ “Conditional shorthands”? Better tell its real name, so those interested in more details can find it in the documentation: ternary operator. \$\endgroup\$ Commented Jan 2, 2014 at 17:53
-
3\$\begingroup\$ The question asks for tips which are somewhat specific to PHP. This is one included in the tips for all languages. \$\endgroup\$ Commented Mar 17, 2014 at 20:35
-
3\$\begingroup\$ The ternary operator has a weird behaviour in PHP, if you nest it.
a?aa:ab?aba:abb:b
evaluates to(a?aa:ab)?(aba):(abb)
or something like that. \$\endgroup\$– TitusCommented Jul 22, 2016 at 19:52 -
1\$\begingroup\$ And starting with PHP 5.3, you can omit the second operator:
$a?:$b
is the same as$a?$a:$b
. \$\endgroup\$– TitusCommented Jul 22, 2016 at 19:55 -
1\$\begingroup\$ @Cyoce
||
casts to boolean in PHP. \$\endgroup\$– TitusCommented Jan 5, 2017 at 23:29
Combining for
loops
Suppose you have code of the following form:
for($pre1; $cond1; $post1) for($pre2; $cond2; $post2) $code;
this can generally be re-rolled in the following form:
for($pre1; $cond2 • $post2 || $cond1 • $pre2 • $post1; ) $code;
where •
represents a generic combining operator. This usually results in an byte count reduction, but will likely require some creativity. $cond2
will need to be written so that it fails the first time through. $post1
should also fail to execute the first time, although it may be easier to refactor beforehand so that $post1
is not present.
If you're working with three or more nested loops, you can also combine two first, and then combine that to another, and so on. I find that it has generally been easier to combine from the inside outwards.
As an example, consider the following solution to the H-carpet fractal (97 bytes):
for(;$i<$n=3**$argn;$i+=print"$s\n")for($s=H,$e=1;$e<$n;$e*=3)$s.=str_pad($i/$e%3&1?$s:'',$e).$s;
This can be reformulated in the following way:
for(;($i+=$e&&print"$s\n")<$n=3**$argn;)for($s=H,$e=1;$e<$n;$e*=3)$s.=str_pad($i/$e%3&1?$s:'',$e).$s;
$e&&print
prevents print
on first iteration, and also does not increment $i
.
and finally (93 bytes):
for(;$H>$e*=3or$e=($i+=$e&&print"$s\n")<${$s=H}=3**$argn;)$s.=str_pad($i/$e%3&1?$s:'',$e).$s;
$H>$e*=3
will fail the first time as both variables are undefined.
line breaks
if the output requires line breaks, use a physical line break (1 byte) instead of "\n"
This also gives you a possible benefit to chose between single and double quotes.
Associative arrays can be merged with the +
operator.
Instead of:
$merged = array_merge($a, $b);
Use:
$merged = $a + $b;
Note the +
operator works with indexed arrays as well, but probably doesn't do what you want.
-
2\$\begingroup\$ Indeed, frequently a good replacement, though not exactly the same: pastebin.com/seYeaP38 \$\endgroup\$ Commented Jan 5, 2017 at 19:46
-
\$\begingroup\$ Ah yeah, dang it, I originally had the title "associative arrays ... " and then removed it. I'll clarify, thanks. \$\endgroup\$ Commented Jan 5, 2017 at 19:56
-
\$\begingroup\$ numeric arrays can also merged using
+
, as long as the indexes are distinct. If they are not, the values from the first array will be overwritten with those from the second one (just like array_merge). The difference:+
does not reorder indexes. \$\endgroup\$– TitusCommented Jan 6, 2017 at 0:11
Use boolean operators instead of strtoupper()
and strtolower()
If you're working exclusively with strings consisting of alphabet characters, you can use boolean operators to change them to uppercase or lowercase with fewer keystrokes than PHP's built-in functions.
Example:
// Convert lowercase to uppercase
$s = "g";
echo strtoupper($s); // Outputs 'G', uses 20 characters
echo~" "&$s; // Outputs 'G', uses 12 characters
// Convert uppercase to lowercase
$s = "G";
echo strtolower($s); // Outputs 'g', uses 20 characters
echo$s^" "; // Outputs 'g', uses 11 characters
// Switch case of each character
$s = "Gg";
echo$s^" "; // Outputs 'gG', uses 12 characters
Things are a little trickier for strings of arbitrary length, but the &
and ^
operators will truncate the result to the length of the shorter input string. So for example, if $W
is a string of spaces at least as long as any input $s
, then ~$W&$s
is equivalent to strtoupper($s)
, and $s|$W^$s
is equivalent to strtolower($s)
(whereas $s|$W
by itself will produce a string with additional spaces unless $s
and $W
are of equal length).
PCRE-Related (Regex)
Functions
If the pattern always matches the subject string (thanks to the comment by @Deadcode), instead of preg_replace
, you can use preg_filter
(1 byte shorter).
Patterns
Sometimes espace sequences are useful, like \d
, \w
, \W
, \s
or \S
.
Examples
Filter non-alphabet characters:
preg_replace("/[^a-z]/i", "", $s);
preg_filter("/\W|\d/", "", $s); // 3 bytes shorter
-
1\$\begingroup\$ Welcome to Code Golf, and nice tip! \$\endgroup\$– rydwolfCommented Feb 8, 2022 at 16:46
-
\$\begingroup\$ @taRadvylfsriksushilani, thanks you very much! :) \$\endgroup\$ Commented Feb 8, 2022 at 18:24
-
\$\begingroup\$ Note that this only works if the regex always matches. If it doesn't, it may still be made to work by adding a
|
at the end of the regex to make it match even when it doesn't match, but then there's no byte savings anymore. Also I'm not sure why you're showing/[^a-z]/i
forpreg_replace
but/\W|\d/
forpreg_filter
– they both use PCRE and anything that works in the latter should work in the former. \$\endgroup\$– DeadcodeCommented Aug 2, 2022 at 3:27 -
\$\begingroup\$ @Deadcode, thanks for the note, added in the answer. And about your last note: I know, but I just wanted to show these two tricks together can shorten the code by 3 characters. \$\endgroup\$ Commented Aug 2, 2022 at 11:21
avoid quotes where possible
PHP implicitly casts unknown words to literal strings.
$foo=foo;
is the same as $foo='foo';
(assuming that foo
is neither a key word or a defined constant): $foo=echo;
does not work.
BUT: $p=str_pad;
does; and $p(ab,3,c)
evaluates to abc
.
Using string literals without quotes will yield a Notice for Use of undefined constant
; but that won´t show if you use the default value for error_reporting
(CLI parameter -n
).
-
\$\begingroup\$ I just noticed: This answer is a somewhat extended/updated duplicate of codegolf.stackexchange.com/a/2916/55735. \$\endgroup\$– TitusCommented Jan 17, 2017 at 2:49
-
\$\begingroup\$ Note: PHP before 7.2 yielded Notices (which you can opress with the
-n
flag); 7.2 yields Warnings; later versions will throw Errors! \$\endgroup\$– TitusCommented Feb 22, 2019 at 15:17
intersecting strings
Have you ever used
join("DELIMITER",str_split($s))
(31 bytes) or even
preg_replace(".","DELIMITER",$s)
(32 bytes)
?
There´s a builtin for that:
Try chunk_split($s,1,"DELIMITER")
(29 bytes).
If you omit the third parameter, chunk_split
will use \r\n
; that can save you 7 or 8 bytes.
But beware: chunk_split
also appends the delimiter to the string,
so you may not get exactly what you want.
(If you don´t provide the chunk length, it will use 76. Rather unusual for code golf, but who knows.)
-
\$\begingroup\$ Maybe you should add an example in combination with
strtr
I love this idea. \$\endgroup\$ Commented May 19, 2017 at 0:41
array_merge vs array_push
array_push($a,...$b);
is one byte shorter than
$a=array_merge($a,$b);
Does not work the same with Associative arrays
-
1\$\begingroup\$ This is an older tip now, but don't miss out on
$a=[...$a,...$b]
too! \$\endgroup\$ Commented Aug 2, 2022 at 11:57
Arrow functions in PHP 7.4
PHP 7.4 is on RC2 version now and hopefully will be released in about 2 months. List of new features are here (this page can actually be updated when 7.4 is released). In 7.4, finally PHP has got the arrow functions, so not only function answers can be shorter now, but also passing closures to other functions can be a lot shorter too. Here are a few examples:
Return input + 1:
Anonymous function (closure) - 25 bytes - Try it online!
function($n){return$n+1;}
Arrow function - 12 bytes - Try it online!
fn($n)=>$n+1
Multiply items of first input (array of ints) by second input (int):
Anonymous function (closure) - 72 bytes - Try it online!
function($a,$n){return array_map(function($b)use($n){return$b*$n;},$a);}
Arrow function - 38 bytes - Try it online!
fn($a,$n)=>array_map(fn($b)=>$b*$n,$a)
Did you notice that $n
is accessible in the inner function without a use $n
statement? Yeah that is one of the arrow function features.
As a side note, I could not get arrow functions to work recursively (call the same arrow function inside itself), because we cannot give them a name and storing them as a closure in a variable like $f
doesn't make $f
accessible withing itself (sad). So this example doesn't work and using $f
in first line causes a fatal error:
$f=fn($n)=>$n?$f($n-1):0;
$f(5); // Causes error: "PHP Notice: Undefined variable: f" + "PHP Fatal error: Uncaught Error: Function name must be a string"
But calling an arrow function withing a different arrow function works:
$f1=fn($n)=>$n+1;
$f2=fn($n)=>$f1($n-1);
$f1(2) // Returns 3
$f2(2) // Returns 2
-
\$\begingroup\$ What if instead of
$f=fn($n)=>$n?$f($n-1):0;
you do$f=$F=fn($n)=>$n?$F($n-1):0;
? Would that work? And then you call$(5)
as usual. \$\endgroup\$ Commented Oct 3, 2019 at 18:01 -
\$\begingroup\$ @IsmaelMiguel it still seems to throw same error. You can actually try on tio.run#php yourself as Dennis has updated its PHP to 7.4 RC2 a while back. \$\endgroup\$– Night2Commented Oct 3, 2019 at 19:20
-
\$\begingroup\$ Can't get it to work. Seems that only variables defined before are available. \$\endgroup\$ Commented Oct 4, 2019 at 8:34
Regarding file I/O:
Linking to another related question, the answers to which fit here.
Use negative indexes to reference the end of a string
If you need the last character in a string, you can use the array reference method, and provide a negative index:
$lastChar = $string[-1];
This also works for functions like substr()
:
$lastFour = substr($string, -4);
Directly dereference arrays returned from functions.
E.g., instead of this:
$a = foo();
echo $a[$n];
You can do:
echo foo()[$n];
This works with methods too:
echo $obj->foo()[$n];
You can also directly dereference array declarations:
echo [1, 2, 3, 4, 5][$n];
Use end()
instead of array_pop()
The end()
function doesn't just move the internal pointer to the end of the array, it also returns the last value. Note of course that it doesn't remove that value, so if you don't care what the array contains afterwards, you can use it instead of array_pop()
.
double array_flip vs in_array vs array_unique
in this special case a double array_flip saves 10 Bytes
($f=array_flip)($k=$f($c)))
remove all double values in the array
and I have dropped this $c=[],
, |in_array($o,$c)
and replace array_keys($c)
with $k
for([,$x,$y]=$argv;a&$o=$y[$i];$i++)
$x[$i]==$o?:$c[$x[$i]]=$o; # if char string 1 not equal char string 2 set key=char1 value=char2
echo strtr($x,($f=array_flip)($k=$f($c)))==$y # boolean replacement string 1 equal to string 2
?join($k)." ".join($c) # output for true cases
:0; #Output false cases
against
for($c=[],[,$x,$y]=$argv;a&$o=$y[$i];$i++)
$x[$i]==$o|in_array($o,$c)?:$c[$x[$i]]=$o; # if char string 1 not equal char string 2 set key=char1 value=char2
echo strtr($x,$c)==$y # boolean replacement string 1 equal to string 2
?join(array_keys($c))." ".join($c) # output for true cases
:0; #Output false cases
against array_unique it saves 2 Bytes
for([,$x,$y]=$argv;a&$o=$y[$i];$i++)
$x[$i]==$o?:$c[$x[$i]]=$o; # if char string 1 not equal char string 2 set key=char1 value=char2
echo strtr($x,array_unique($c))==$y # boolean replacement string 1 equal to string 2
?join(array_keys($c))." ".join($c) # output for true cases
:0; #Output false cases
After finding a bug in this program and replacement $x[$i]==$o?:$c[$x[$i]]=$o
to ($p=$x[$i])==$o?:$k[$c[$p]=$o]=$p
the double array_flip was not necessary longer
-
\$\begingroup\$ associative safe
array_unique
. Yay! \$\endgroup\$– TitusCommented Apr 19, 2017 at 11:03 -
\$\begingroup\$ @Titus I have add your suggestion \$\endgroup\$ Commented Apr 19, 2017 at 13:49
Return two copies of an expression
If you want to get two copies of the result of an expression, you can use this:
$v.$v=expr
But it won't be shorter than the more straightforward ($v=expr).$v
if you need to append more things to the result.
For 4 copies:
$v.$v.=$v=expr
You cannot use it to get 3 copies.
unset() vs INF
In a case search for a minimum in an array you can use instead of
unset($var[$k]);
$var[$k]=INF;
to save 3 Bytes