Convert JSON string to Key / Value Arrays

4

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??

loxxy

Posted 2013-03-15T11:02:51.763

Reputation: 209

1What 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 – 2013-03-15T14:00:49.680

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 – 2013-03-15T15:50:33.447

4function keys(x){return Object.keys(JSON.parse(x))}... – Shmiddty – 2013-03-15T21:55:12.933

Answers

7

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)

grc

Posted 2013-03-15T11:02:51.763

Reputation: 18 565

5

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

Graham

Posted 2013-03-15T11:02:51.763

Reputation: 3 184

2

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

primo

Posted 2013-03-15T11:02:51.763

Reputation: 30 891

2

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}

wolfhammer

Posted 2013-03-15T11:02:51.763

Reputation: 1 219

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 – 2013-05-07T03:33:53.430

69 per proc is the best I could get. It looks like Johannes Kuhn has a good one for Tcl 8.6. – wolfhammer – 2013-05-08T22:51:44.797

You can shorten a bit because you are regex' tagging expressions you don't need, so you can remove some (): http://rextester.com/EFMSXX16344

– sergiol – 2017-06-20T11:53:48.660

May be I am wrong, but I think you also don't need 0 at the end. – sergiol – 2017-06-20T11:56:26.593

1

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"

tmartin

Posted 2013-03-15T11:02:51.763

Reputation: 3 917

1

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));}

Mr. Llama

Posted 2013-03-15T11:02:51.763

Reputation: 2 387

1

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

Adám

Posted 2013-03-15T11:02:51.763

Reputation: 37 779

1

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.

Gabriel Mills

Posted 2013-03-15T11:02:51.763

Reputation: 778

keys and values – mazzy – 2020-01-15T05:30:00.640

0

CoffeeScript:

vals = []
keys = []
vals.push(v) and keys.push(k) for own k, v of JSON.parse(X)

phenomnomnominal

Posted 2013-03-15T11:02:51.763

Reputation: 101

0

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

histocrat

Posted 2013-03-15T11:02:51.763

Reputation: 20 600

0

Lua

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

68 and 71 chars

mniip

Posted 2013-03-15T11:02:51.763

Reputation: 9 396

0

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.

Johannes Kuhn

Posted 2013-03-15T11:02:51.763

Reputation: 7 122

0

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)))()

mickmackusa

Posted 2013-03-15T11:02:51.763

Reputation: 121

0

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

Merin Nakarmi

Posted 2013-03-15T11:02:51.763

Reputation: 247

0

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

DeathIncarnate

Posted 2013-03-15T11:02:51.763

Reputation: 916