ckersch
ckersch

Reputation: 7687

What's the best way to restructure a javascript object?

I'm restructuring an object in javascript to turn a flat object:

{
    'we' : 'are',
    'the' : 'knights',
    'who' : 'say',
    'ni' : '!!!'
}

into an object in which some of the items previously in the flat object are contained in a child of the original flat object:

{
    'we' : 'are',
    'the' : 'knights',
    'shrubbery' : {
        'who' : 'say',
        'ni' : '!!!'
    }
}

I can do this restructuring by referencing an then deleting, like so:

var knights = {
    'we' : 'are',
    'the' : 'knights',
    'who' : 'say',
    'ni' : '!!!'
};

knights.shrubbery = {'who':knights.who,
                     'ni':knights.ni};

delete knights.who;
delete knights.ni;

but this seems inelegant. Is there a better way to move attributes of one object to a different object or otherwise bundle attributes of an object into a child of that object?

Ultimately, what I'm trying to do is form a flat object into a data tree, in which the root root object can contain groups which contain subgroups and so on. Something like turning this:

{'leaf1':'',
 'leaf2':'',
 'leaf3':'',
 'leaf4':'',
 'leaf5':'',
 'leaf6':'',
 'leaf7':'',
 'leaf8':'',
 'leaf9':''
}

into this:

{'leaf1':'',
 'leaf2':'',
 'leaf3':'',
 'groups' : [
     {
         'leaf1':''
     },{
     'leaf1':'',
     'leaf2':'',
     'groups':[
         {
         'leaf7':'',
         'leaf8':'',
         'leaf9':''
         }
     ]
     }
]
}

Upvotes: 2

Views: 1762

Answers (2)

Dan Tao
Dan Tao

Reputation: 128307

I'd suggest writing a method to do something like this in the general case. I wouldn't recommend mutating the object in place, just because more often than not you'll get more use out of one that creates a copy instead.

Here's an idea: how about the method signature takes:

  1. An object
  2. A property name
  3. A list of property names to nest inside the new property

Like this:

function nestProperties(obj, property, nestedProperties)
{
  var newObj = {};
  var nestedObj = {};

  for (var i = 0; i < nestedProperties.length; ++i)
  {
    if (nestedProperties[i] in obj)
    {
      nestedObj[nestedProperties[i]] = obj[nestedProperties[i]];
    }
  }

  for (var k in obj)
  {
    if (!(k in nestedObj))
    {
      newObj[k] = obj[k];
    }
  }

  newObj[property] = nestedObj;

  return newObj;
}

You would use this like so:

var flat = {
  'we' : 'are',
  'the' : 'knights',
  'who' : 'say',
  'ni' : '!!!'
};

var knights = nestProperties(flat, 'shrubbery', ['who', 'ni']);

Upvotes: 1

Andrew Clark
Andrew Clark

Reputation: 208475

I don't think there is anything wrong with your current method, but to make it a bit more extensible you could wrap it in a function:

function restructure(obj, new_child, properties) {
    obj[new_child] = {};
    for (var i = 0; i < properties.length; i++) {
        obj[new_child][properties[i]] = obj[properties[i]];
        delete obj[properties[i]];
    }
}

restructure(knights, 'shrubbery', ['who', 'ni']);

Upvotes: 1

Related Questions