Converting a 2D array to a JSON list

Posted on

Problem

I am wondering if I could implement this in a cleaner, more elegant, strictly functional way:

const convert2dArrayToJsonList = (array) => {

    if (!is2dArrayParsableToJsonList(array)) {
        throw new Error("The 2D array cannot be converted to a json list" + array);
    }

    const propertyKeys = array[0];

    return array
        .slice(1)
        .map( row => {
            return row.reduce( (accumulatedElement, propertyValue, currentIndex, array) => {

                accumulatedElement[propertyKeys[currentIndex]] = propertyValue;
                return accumulatedElement;
            }, {});
        });
}

The implementation of is2dArrayParsableToJsonList(array) is not relevant in this context, it does what it says.

The 2D array parameter has the property keys in the top row and all other rows represent individual elements in the list.

Solution

Here’s what I’ve come up with;

import expect from 'expect';

const is2dArrayParsableToJsonList = () => true;

const convert2dArrayToJsonList = (array) => {

    if (!is2dArrayParsableToJsonList(array)) {
        throw new Error("The 2D array cannot be converted to a json list" + array);
    }

    const [propertyKeys, ...rows] = array;
    const rowToObject = row => Object.assign(... propertyKeys.map( (key,idx) => ({ [key]: row[idx] })));
    return rows.map(rowToObject);
}

const input = [
    ['foo', 'bar', 'baz'],
    [1,2,3],
    [4,5,6]
];

const output = [
    {foo:1, bar:2, baz:3},
    {foo:4, bar:5, baz:6},
];

expect(convert2dArrayToJsonList(input)).toEqual(output);

Core idea is that map gives you both a value and index. So when you map over the keys, we see ‘foo/1’, ‘bar/2’, ‘baz/3’.

Leave a Reply

Your email address will not be published. Required fields are marked *