Trying my hand at (code) golf

Ben Pickles
Mar 30, 2017 · 3 min read

I’ve never attempted code golf before but encountered the following tweet that looked achievable.

JS Golf #4: play(“hello=goodbye&answer=42&x=y”) === {hello:”goodbye”,answer:”42”,x:”y”} (parse url encoded parameter strings into objects)

JS Golf #4

I thought I’d describe the journey to my shortest solution (lower score is better) which ended up touching on a few of JavaScript’s newer language features.

An unoptimised solution

Here’s my starting “normal” code that does the job.

function play(querystring) {
return querystring.split('&').reduce(function(object, param) {
const parts = param.split('=')
object[parts[0]] = parts[1]
return object
}, {})
}

Score: 104

Apply some manual minification.

function play(q){return q.split('&').reduce(function(o,p){let k=p.split('=');o[k[0]]=k[1];return o},{})}

Score: 81

Arrow functions are shorter, don’t require parentheses when there’s a single argument, and implicitly return when used without braces.

play=q=>q.split('&').reduce((o,p)=>{let a=p.split('=');o[a[0]]=a[1];return o},{})

Score: 79

Use destructuring assignment.

play=q=>q.split('&').reduce((o,p)=>{let [k,v]=p.split('=');o[k]=v;return o},{})

Score: 75

Don’t worry about setting global variables 😱

play=q=>q.split('&').reduce((o,p)=>{[k,v]=p.split('=');o[k]=v;return o},{})

Score: 71

Template literals also call a function so there’s no need for parentheses.

play=q=>q.split`&`.reduce((o,p)=>{[k,v]=p.split`=`;o[k]=v;return o},{})

Score: 65

Arrow function implicit returns again. I couldn’t use a semicolon to turn the function body into a single line but a comma works.

play=q=>q.split`&`.reduce((o,p)=>([k,v]=p.split`=`,o[k]=v)&&o,{})

Score: 64

Using another comma instead of && is possible as the comma operator returns the last expression.

play=q=>q.split`&`.reduce((o,p)=>([k,v]=p.split`=`,o[k]=v,o),{})

Score: 60

I started looking at whether I could use something other than reduce as its multiple arguments mean parenthesis can’t be removed. In the good old days before ES5 introduced reduce and friends I would have created the data object manually by looping through the array adding properties to it like so:

function play(querystring) {
var object = {}
var params = querystring.split('&')

for (var i = 0; i < params.length; i++) {
var keyvalue = params[i].split('=')
object[keyvalue[0]] = keyvalue[1]
}

return object
}

It turns out that this technique actually shortens the code by a further 4 characters, particularly as nowadays we don’t need to use a verbose for loop. So play now loops over the querystring’s parameters setting key/value pairs on an accumulator object which it then returns — using map instead of forEach for its shorter name.

o={},play=q=>q.split`&`.map(p=>([k,v]=p.split`=`,o[k]=v))&&o

The winner? Yes!

This solution currently shares the top score of 60 characters — someone got there first with an essentially identical version.

It’s been an interesting exercise and taking a deeper look into some of JavaScript’s features has been useful — despite being focussed on hacky ways to shorten code. Re-adding whitespace and proper variable names gives us the shape of the code which looks remarkably Lisp-ish and very un-JavaScript.

object = {},
play = querystring =>
querystring.split `&`
.map(
param => (
[key, value] = param.split `=`,
object[key] = value
)
) && object

Bonus round: a different approach. Score: 63

I wondered if something could be done about the two uses of split so tried a different approach, this time creating an array of key/values with a single split. Combined with the lessons learned so far it’s a good effort but falls just short at 63 characters.

o={},play=q=>q.split(/[&=]/).map((p,i,a)=>i%2?o[a[i-1]]=p:p)&&o

Update: Thanks to @Benjie for removing another valuable character:

o={},play=q=>q.split(/&|=/).map((p,i,a)=>i%2?o[a[i-1]]=p:p)&&o

For good measure here it is deminified:

object = {},
play = querystring =>
querystring.split(/&|=/)
.map(
(param, index, array) =>
index % 2
? object[array[index - 1]] = param
: 1
) && object

Originally published at www.benpickles.com

Ben Pickles

Written by

Listener of Zappa • writer of Ruby and JavaScript • creator of https://github.com/benpickles/peity • leader of thought

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade