Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

Convert JSON (key/value pairs) to a native arrays of keys & values, in your language.

var X = '{"a":"a","b":"b","c":"c","d":"d","e":"e","f":"f9","g":"g2","h":"h1"}';

The value array could be an array of strings or integers.

So we need two functions keys & vals, returning native arrays on input of JSON string.

In above example the output would be:

keys : ["a", "b", "c", "d", "e", "f", "g", "h"]
vals : ["a", "b", "c", "d", "e", "f9", "g2", "h1"]

Here is my attempt at this using javascript:

keys : (53 Chars)

function keys(X){return X.match(/[a-z0-9]+(?=":)/gi)}

vals : (56 Chars)

function vals(X){return X.match(/[a-z0-9]+(?="[,}])/gi)}

Can other languages challenge this??

share|improve this question
1  
What assumptions are you making about the input? You seem to be assuming that it's a single JSON object all of whose member values are strings, and none of whose names or values require escaping. Those assumptions seem to be rather unmotivated / arbitrary. –  Peter Taylor Mar 15 '13 at 14:00
    
I know. But you could say it's a JSON with some constraints. It need not be arbitrary since we could find such cases a lot, in a practical data set. Besides, answers handling the general set would be more than welcome... (as in one of the answers) –  loxxy Mar 15 '13 at 15:50
2  
function keys(x){return Object.keys(JSON.parse(x))}... –  Shmiddty Mar 15 '13 at 21:55
add comment

10 Answers

up vote 5 down vote accepted

Python, 27/30

To actually comply with the rules:

keys=lambda x:list(eval(x))
vals=lambda x:eval(x).values()

Python, 30

Just using one function:

lambda x:zip(*eval(x).items())

This will separate the keys from the values and return them in a list.

Python, 7

If returning a dictionary is allowed, then this is all you need:

eval(x)
share|improve this answer
add comment

CoffeeScript:

vals = []
keys = []
vals.push(v) and keys.push(k) for own k, v of JSON.parse(X)
share|improve this answer
add comment

APL 32

Index origin 1. If you will accept the keys and values being returned as a two row array then a simple one liner will do the job in APL. This takes screen input via ←⍞

⍉((.5×⍴j),2)⍴j←(~j∊'{":;,}')⊂j←⍞

Taking the given example as input:

{"a":"a","b":"b","c":"c","d":"d","e":"e","f":"f9","g":"g2","h":"h1"};

a b c d e f  g  h
a b c d e f9 g2 h1
share|improve this answer
add comment

Perl 28 bytes

Instead of 2 separate functions to return keys and values, I'm returning both in the form of a hash.

sub j2h{eval pop=~y/:"/,/dr}

Sample usage:

$_='{"a":"a","b":"b","c":"c","d":"d","e":"e","f":"f9","g":"g2","h":"h1"}';
%h=j2h($_);
print $h{f}; # prints f9
print $h{g}; # prints g2

It even works for arbitrarily deeply nested variables:

$_='{"a":{"b":{"c":"c3","d":"d4"},"c":"c5"},"b":"b6"}';
%h=j2h($_);
print $h{a}{b}{d}; # prints d4
print $h{a}{c};    # prints c5
share|improve this answer
add comment

K, 22

{+`$":"\:'","\:1_-1_x}

The double quotes in the input string have to be escaped

k){+`$":"\:'","\:1_-1_x} "{\"a\":\"a\",\"b\":\"b\",\"c\":\"c\",\"d\":\"d\",\"e\":\"e\",\"f\":\"f9\",\"g\":\"g2\",\"h\":\"h1\"}"
"a" "b" "c" "d" "e" "f"  "g"  "h"
"a" "b" "c" "d" "e" "f9" "g2" "h1"

For the same bytecount you could just read from stdin

+`$":"\:'","\:1_-1_0:0

.

k)+`$":"\:'","\:1_-1_0:0
{"a":"a","b":"b","c":"c","d":"d","e":"e","f":"f9","g":"g2","h":"h1"}
"a" "b" "c" "d" "e" "f"  "g"  "h"
"a" "b" "c" "d" "e" "f9" "g2" "h1"
share|improve this answer
add comment

Ruby, 19

eval X.gsub':','=>'

Similar, unsurprisingly, to the Perl solution. The Ruby 1.9 literal for a Hash would be identical to the input form if it weren't for the quoted keys; as it is we just need to convert the colons to =>.

share|improve this answer
add comment

PHP, 56/58

Pssh, PHP has functions for this stuff (although it won't win the shortest answer award).

function keys($j){return array_keys(json_decode($j,1));}
function vals($j){return array_values(json_decode($j,1));}
share|improve this answer
add comment

Tcl 69,69

first attempt 132 keys+vals

proc j {x n} {
regsub -all {(".*?"):(".*?")} $x "\[lappend o \\$n\]" x
subst $x
set o $o
}
proc keys x {j $x 1}
proc vals x {j $x 2}

second try 69 keys, 69 values

proc keys x {regsub -all {(".*?"):(".*?").} $x {\1 } x
lindex $x\} 0}

proc vals x {regsub -all {(".*?"):(".*?").} $x {\2 } x
lindex $x\} 0}
share|improve this answer
    
Compared to the answers, this one is very, very long. Is there a way you can compact this down, to (say) less than 50 characters? –  Chris Jester-Young May 7 '13 at 3:33
    
69 per proc is the best I could get. It looks like Johannes Kuhn has a good one for Tcl 8.6. –  user1455003 May 8 '13 at 22:51
add comment

Lua

function keys(x)return loadstring("return"..x:gsub(':".-"',''))()end
function vals(x)return loadstring("return"..x:gsub('"[^"]*":',''))()end

68 and 71 chars

share|improve this answer
add comment

Tcl 8.6, 82

 package r json;lmap keys [dict k [set d [json::json2dict $X]]] vals [dict v $d] {}

The Tcl core is (unlike php) very small.
This requires the tcllib, which is available as package for most linux distributions.
I use this library because too much languages have a json_parse build in.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.