3

I'm looking for a way in which I can achieve the following transformation: enter image description here

The following code contains the old + new structure:

function test_cleanHierarchyUp() {
  console.log("Test for cleaning up hierarchy")
  // I don't have children, so just keep me as is.
  var bottom_level_object = {
    'test': 'testest',
    'more test': 'test',
    'test': ''
  }

  var middle_object = {
    children: bottom_level_object,
    Name: "Middle Yeah!"
  }

  var original_object = [{
      Name: "I am a name",
      RandomName: '',
      Children: middle_object
    },
    {
      Name: "I am a name too",
      Children: bottom_level_object
    }
  ]

  console.log("-----")
  console.log("Source object: ")
  console.log(original_object)

  // Target structure:
  // I don't have children, so just keep me as is.
  var bottom_level_object_new = {
    'test': 'testest',
    'more test': 'test'
  }

  // Empty string (object 'Random') was removed from object.
  var middle_object_new = {
    "Middle Yeah!": {
      children: bottom_level_object,
      Name: "Middle Yeah!"
    }
  }

  var target_object = {
    "I am a name": {
      Name: "I am a name",
      Children: middle_object_new
    },
    "I am a name too": {
      Name: "I am a name too",
      Children: bottom_level_object_new
    }
  }
  console.log("-----")
  console.log("Target object: ")
  console.log(target_object)

}

I did try: Recursion still hasn't dropped for me, unfortunately. A minor addition is in the code, in the same recursion function I'd like to remove all attributes for which the value is an empty string.

// Hierarchy Clean up functions
// Todo with this datastructure
//   - How do I remove all fields with value of ""
//   - For each object in the tree, change the object's key into its 'Name' attribute
function cleanHierarchyUp(obj) {
  // obj is an array of objects, with or without a 'children' object (array of objects again)
  // Goal: the object name should be its '.Name' name attribute if it exists
  // Goal: if possible: all 'keys' for which the value is an empty string should be removed.
  obj.forEach(function(element, index) {
    // console.log(element)
    if (element.Children) {
      obj[element.Name] = cleanHierarchyUp(element)
    } else {
      obj[element.Name] = element
    }
  })
  return obj
}

Help or direction is greatly appreciated.

MattV
  • 1,353
  • 18
  • 42
  • 1
    Are you starting with individual small objects or a complete array that you need to iterate? Providing actual sample data and not images of data would be helpful also – charlietfl Feb 05 '17 at 14:16
  • 1
    The transformation for `Middle Yeah!` doesn't make any sense!! – ibrahim mahrir Feb 05 '17 at 14:21
  • @charlietfl: The raw data is in the code provided. – MattV Feb 05 '17 at 14:53
  • So basically you are trying to convert an Array into an object at every step. Right? – Anubhav Feb 05 '17 at 14:55
  • That doesn't answer question. This whole thing smells like an [XY Problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). What is use case? – charlietfl Feb 05 '17 at 14:55
  • Basically the original JSON is what I get back from loading a flat row-based hierarchical representation of a configuration object. It's created from something that looks like this: https://stackoverflow.com/questions/31383869/converting-flat-structure-to-hierarchical. I'd like to be able to access the properties simply by obj["I am a name"] in the resulting data structure. Hope this makes sense, How could I clarify further? – MattV Feb 05 '17 at 15:05
  • @Anubhav I'm not trying to turn all arrays into objects, the final structure will still have multiple 'array of objects' in the children property. Does this make sense? EDIT: I see what you mean, I'll try to understand what I'm doing here a bit more and edit. – MattV Feb 05 '17 at 15:07
  • My edited answer should work for you. – Jeremy Jackson Feb 05 '17 at 15:54
  • There are lots of ways to search and filter arrays by property names or map arrays to objects. Think you need to explain what you need to accomplish in more detail. Example shown conflicts with your recent comments since expected result shown is all one object with no arrays in it – charlietfl Feb 05 '17 at 16:31

1 Answers1

1

I believe this does what you want:

function createObjectFromArray(objArr) {
    console.log('objArr', objArr);
    var newObject = {};
    objArr.forEach(function(object, index) {
        if (!object.hasOwnProperty('Name') || object.Name.length < 1) return;
        var objectName = object.Name;
        console.log(objectName)
        newObject[objectName] = {};
        newObject[objectName] = setObjectKeys(object, newObject[objectName])
    });
    console.log('newObject', newObject)
    return newObject;
}

function setObjectKeys(object, newObject) {
    Object.keys(object).forEach(function(key){
        if ((typeof object[key] == 'string')) {
            if (object[key].length > 0) {
                newObject[key] = object[key];
            }
        } else if (keyIsObject(object, key)) {
            newObjectKey = key;
            if(object[key].Name) {
                newObjectKey = object[key].Name;
            }
            newObject[newObjectKey] = setObjectKeys(object[key], {});
        } else {
            newObject[key] = object[key];
        }
    });
    return newObject;
}

function keyIsObject(object, key) {
    return Object.prototype.toString.call(object[key]) === '[object Object]';
}

var bottom_level_object = {
    'test': 'testest',
    'more test': 'test',
    'test': ''
}

var middle_object = {
    children: bottom_level_object,
    Name: "Middle Yeah!"
}

var original_object = [{
    Name: "I am a name",
    RandomName: '',
    Children: middle_object
}, {
    Name: "I am a name too",
    Children: bottom_level_object
}];

createObjectFromArray(original_object);
Jeremy Jackson
  • 2,247
  • 15
  • 24