2
\$\begingroup\$

Convert JSON (key/value pairs) to two native arrays, one array of keys and another of 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??

\$\endgroup\$
  • 1
    \$\begingroup\$ 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. \$\endgroup\$ – Peter Taylor Mar 15 '13 at 14:00
  • \$\begingroup\$ 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) \$\endgroup\$ – loxxy Mar 15 '13 at 15:50
  • 4
    \$\begingroup\$ function keys(x){return Object.keys(JSON.parse(x))}... \$\endgroup\$ – Shmiddty Mar 15 '13 at 21:55

11 Answers 11

5
\$\begingroup\$

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)
\$\endgroup\$
4
\$\begingroup\$

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
\$\endgroup\$
2
\$\begingroup\$

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
\$\endgroup\$
2
\$\begingroup\$

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}
\$\endgroup\$
  • \$\begingroup\$ 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? \$\endgroup\$ – Chris Jester-Young May 7 '13 at 3:33
  • \$\begingroup\$ 69 per proc is the best I could get. It looks like Johannes Kuhn has a good one for Tcl 8.6. \$\endgroup\$ – wolfhammer May 8 '13 at 22:51
  • \$\begingroup\$ You can shorten a bit because you are regex' tagging expressions you don't need, so you can remove some (): rextester.com/EFMSXX16344 \$\endgroup\$ – sergiol Jun 20 '17 at 11:53
  • \$\begingroup\$ May be I am wrong, but I think you also don't need ` 0` at the end. \$\endgroup\$ – sergiol Jun 20 '17 at 11:56
1
\$\begingroup\$

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"
\$\endgroup\$
1
\$\begingroup\$

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));}
\$\endgroup\$
0
\$\begingroup\$

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 =>.

\$\endgroup\$
0
\$\begingroup\$

CoffeeScript:

vals = []
keys = []
vals.push(v) and keys.push(k) for own k, v of JSON.parse(X)
\$\endgroup\$
0
\$\begingroup\$

Lua

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

68 and 71 chars

\$\endgroup\$
0
\$\begingroup\$

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.

\$\endgroup\$
0
\$\begingroup\$

PHP 7.4+, 39/41 bytes

(demo)

The keys via closure with PHP7.4 arrow function syntax: 39 bytes

(fn()=>array_keys(json_decode($X,1)))()

The values via closure with PHP7.4 arrow function syntax: 41 bytes

(fn()=>array_values(json_decode($X,1)))()
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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