7

I have an array that looks like so:

files = [
  'Dashboard/Logs/Errors',
  'Dashboard/Logs/Other',
  'Accounts/Main',
]

I want to make it look like this:

navigation = [
  {
    "title": "Dashboard",
    "dropdown": [
      {
        "title": "Logs",
        "dropdown": [
          {
            "title": "Errors",
          },
          {
            "title": "Other",
          }
        ]
      }
    ]
  },
  {
    "title": "Accounts",
    "dropdown": [
      {
        "title": "Main",
      }
    ]
  }
]

I have the following so far:

var navigation = [];
for (var i = 0; i < files.length; i++) {
  var parts = files[i].split('/');
  navigation.push({title: parts[0]});
  for (var j = 1; j < parts.length; j++) {

  }
}

I am having difficulties figuring out a decent way to do this. What I have so far already doesn't work because it creates two objects under navigation each with title: "Dashboard". Any ideas for a clever approach? Thanks :)

7
  • Whats navigation? navigation = []; ? Commented Feb 18, 2016 at 22:23
  • @Alec Is the depth of the object hierarchy fixed ? or is there a maximum depth atleast ? Commented Feb 18, 2016 at 22:24
  • @kulkarniankita navigation is defined right there. The end result should be navigation. Commented Feb 18, 2016 at 22:24
  • @MikeC right although navigation is something he wants as a end result so he needs to declare it in order to push elements Commented Feb 18, 2016 at 22:26
  • @kulkarniankita No they don't. They're showing an example output. This does not pertain to the problem. Commented Feb 18, 2016 at 22:26

2 Answers 2

7

This should produce the desired output:

var files = [
  'Dashboard/Logs/Errors',
  'Dashboard/Logs/Other',
  'Accounts/Main',
];

var navigation = [];
// Iterates through a navigation array and returns the object with matching title, if one exists.
var getNavigationObject = function(nav, title) {
  for (var i = 0; i < nav.length; i++) {
    if (nav[i].title == title) {
      return nav[i];
    }
  }
};
// Adds a file to the nav.
// The input is an array of file components (i.e. file.split('/'))
// This works by recursively adding each component of a file.
var addToNav = function (nav, components) {
  var n = getNavigationObject(nav, components[0]);
  if (!n) {
    n = {
      title: components[0]
    };
    nav.push(n);
  }
  if (components.length > 1) {
    n.dropdown = n.dropdown || [];
    addToNav(n.dropdown, components.slice(1));
  }
};

// Actually call `addToNav` on each file.
files.forEach(function(e) {
  addToNav(navigation, e.split('/'));
});

// Produces the result in string form.
JSON.stringify(navigation, null, 2)

This works by recursively checking if a given element already matches the component of the file. If it does, it recurs into that component's "dropdown". Otherwise, it creates it.

Sign up to request clarification or add additional context in comments.

1 Comment

Clarified. Wrote it in a hurry--certainly not production level code. :)
1

This is an approach with a temporary object and some array methods with no search overhead.

var files = ['Dashboard/Logs/Errors', 'Dashboard/Logs/Other', 'Accounts/Main'],
    navigation = function (data) {
        var r = [], o = {};
        data.forEach(function (a) {
            var s = r;
            a.split('/').reduce(function (p, b) {
                if (p.children) {
                    p.value.dropdown = p.value.dropdown || [];
                    s = p.value.dropdown;
                    p = p.children;
                }
                if (!(b in p)) {
                    p[b] = { value: { title: b }, children: {} };
                    s.push(p[b].value);
                }
                return p[b];
            }, o);
        });
        return r;
    }(files);

document.write('<pre>' + JSON.stringify(navigation, 0, 4) + '</pre>');

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.