Nadroev
Nadroev

Reputation: 363

How to merge object properties with array indexes in their names into a single array?

I have an object like this

var obj = {
  'Lorem': 'foo',
  'Ipsum[0]': 'bar',
  'Ipsum[1]': 'stuff',
  'Dolor[0][0]': 'foo',
  'Dolor[0][1]': 'bar',
  'Dolor[1][0]': 'stuff',
  'Dolor[1][1]': 'foo'
};

And I'd like to turn it into this

var obj = {
  'Lorem': 'foo',
  'Ipsum': ['bar', 'stuff'],
  'Dolor': [
    ['foo', 'bar'],
    ['stuff', 'foo']
  ]
};

I dug up from here that with .match(/[^\[\]]+/g) I can get the values between the brackets, but I can't figure out what to do with them.

Upvotes: 1

Views: 51

Answers (1)

Nina Scholz
Nina Scholz

Reputation: 386578

You could use the regular expression (i added a dot for nested objects) and reduce the path by walking the given object. If no Object exist, create a new property with the name, or an array. Later assign the value.

function setValue(object, path, value) {
    var way = path.match(/[^\[\].]+/g),
        last = way.pop();

    way.reduce(function (o, k, i, kk) {
        return o[k] = o[k] || (isFinite(i + 1 in kk ? kk[i + 1] : last) ? [] : {});
    }, object)[last] = value;
}

var obj = { 'Lorem': 'foo', 'Ipsum[0]': 'bar', 'Ipsum[1]': 'stuff', 'Dolor[0][0]': 'foo', 'Dolor[0][1]': 'bar', 'Dolor[1][0]': 'stuff', 'Dolor[1][1]': 'foo' };

Object.keys(obj).forEach(function (k) {
    var v = obj[k];
    delete obj[k];
    setValue(obj, k, v);
});

console.log(obj);

Upvotes: 2

Related Questions