6
\$\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\$
4
  • 3
    \$\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\$ Commented Mar 15, 2013 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
    Commented Mar 15, 2013 at 15:50
  • 5
    \$\begingroup\$ function keys(x){return Object.keys(JSON.parse(x))}... \$\endgroup\$
    – Shmiddty
    Commented Mar 15, 2013 at 21:55
  • \$\begingroup\$ I'd VTRO (edit: it's not closed, so I'd not-vote-to-close) this, but there's still a few things that are unclear: Can we have a single function that returns both arrays? What can we assume the keys or values look like? What is a "native array"? \$\endgroup\$
    – rydwolf
    Commented Aug 16, 2021 at 12:36

18 Answers 18

7
\$\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\$
5
\$\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\$
0
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\$
4
  • \$\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\$ Commented May 7, 2013 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
    Commented May 8, 2013 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
    Commented Jun 20, 2017 at 11:53
  • \$\begingroup\$ May be I am wrong, but I think you also don't need ` 0` at the end. \$\endgroup\$
    – sergiol
    Commented Jun 20, 2017 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\$
1
\$\begingroup\$

APL (Dyalog Unicode), 18 bytesSBCS

Anonymous tacit prefix function. Prints list of keys, then returns list of values.

'⍎¨⎕←⎕NL¯2'⍎⍨⎕JSON

Try it online!

⎕JSON convert JSON string to APL namespace object

''⍎⍨ in that namespace, execute the following code:

⎕NL¯2 name list for all all variables

⎕← print that list

⍎¨ execute each name

\$\endgroup\$
1
\$\begingroup\$

PowerShell, 34/36 28/28 bytes

-14 bytes total thanks to @mazzy!

To fetch the keys:

&(gcm *F*son)"$args" -a|% k*

Try it online!

To fetch the values:

&(gcm *F*son)"$args" -a|% v*

Try it online!

Kinda cheap, as it uses the built-in method ConvertFrom-Json -AsHashtable to convert the data from JSON.

\$\endgroup\$
1
  • \$\begingroup\$ keys and values \$\endgroup\$
    – mazzy
    Commented Jan 15, 2020 at 5:30
1
\$\begingroup\$

ECMAScript

I'm surprised no one has proposed a better ECMAScript solution, so here's my simple attempt:

keys: (29 chars)

X=>Object.keys(JSON.parse(X))

values: (31 chars)

X=>Object.values(JSON.parse(X))

\$\endgroup\$
2
  • 1
    \$\begingroup\$ 28 bytes, 30 bytes: X=>Object.keys(eval("1,"+X)), X=>Object.values(eval("1,"+X)) \$\endgroup\$ Commented Aug 15, 2021 at 14:20
  • \$\begingroup\$ @EnderShadow8 Much better than my solution 👏👏👏 \$\endgroup\$
    – Scaccoman
    Commented Aug 16, 2021 at 15:11
1
\$\begingroup\$

jq, 11–∞ bytes

Try it online!

This answer will take some refining, as I'm not yet clear on the rules. It states that two functions are required, but jq doesn't have functions and I don't know how much of our current meta consensus applies to such old posts

The essence is in two snippets:

  • keys: keys
  • values: [.[]]

These are both valid jq programs that each give their respective piece. Counted like this we have 11 bytes. We can also do:

# Return an array of arrays as [keys, values]
[keys, [.[]]]
# Return another nice JSON as {"keys": keys, "values": values}
{keys:keys, values:[.[]]}

I'll add a bit more explanation when the final entry is clearer.

\$\endgroup\$
1
\$\begingroup\$

C (gcc), 103 bytes

char*b[99],**o,*l;f(s,n)char*s;{for(o=b;*s++;l=*s-34?l:++n%4?s+1:(*o++=strndup(l,s-l)));*o=0;return b;}

Try it online!

Usage:

f(input, 2) returns an array with the keys

f(input, 0) returns an array with the values

C (clang), 67 bytes

*l;f(*s,n){for(;*s++;l=*s-34?l:++n%4?s+1:printf("%.*ls\n",s-l,l));}

Writes the output to stdout instead of returning arrays.

Try it online!

\$\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\$
0
\$\begingroup\$

Python 3 (Total 35 characters)

Input JSON String

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

Get Keys(16 characters)

k=eval(X).keys()

Get Values(18 characters)

v=eval(X).values()

Try online

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

Burlesque, 12 bytes

'";;:an2cou[

Try it online!

'";; # Split by "s
:an  # Filter by alphanumeric
2co  # Group in pairs
u[   # Unzip giving array of vals and array of keys
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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