Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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
3  
function keys(x){return Object.keys(JSON.parse(x))}... – Shmiddty Mar 15 '13 at 21:55

10 Answers 10

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

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

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

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

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. – wolfhammer May 8 '13 at 22:51

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

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

CoffeeScript:

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

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

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

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.