2

So I have a task to properly order the files directory. For simplicity, all the documents and files are saved as a flat array. As an identifier to display nested files I have a property uniqueId, that tells me what are the parent directories. Flat array is sorted by uniqueId, so that each child goes after its parent.

Here is an example of the flat array:

[{
 id: 1,
 uniqueId: '1',
 name: 'folder1',
 dir: true
},
{
 id: 2,
 uniqueId: '1.2',
 name: 'test1',
 dir: false
},
{
 id: 3,
 uniqueId: '1.2.3',
 name: 'test2'
 dir: false
},
{
 id: 4,
 uniqueId: '1.2.4',
 name: 'test3'
 dir: true
},
{
 id: 3,
 uniqueId: '1.3',
 name: 'test23'
 dir: true
},
{
 id: 1,
 uniqueId: '1.3.1',
 name: 'test6',
 dir: true
},
]

Which basically represents files directory tree:

1
  1.2
    1.2.3
    1.2.4
  1.3
    1.3.1

I need to display directories first, i.e. those that have dir: true. Thus, the above tree would become:

1
 1.3
    1.3.1
 1.2
    1.2.4
    1.2.3

So as a solution I decided that it's better to convert a flat array into nested object, sort children of each object in the desired way and then transform into flat array back again. So that my flat array would become like this:

{
 id: 1,
 uniqueId: '1',
 name: 'folder1',
 dir: true
 childs: [
  {
   id: 2,
   uniqueId: '1.2',
   name: 'test1',
   dir: false,
   childs: [
   {
     id: 3,
     uniqueId: '1.2.3',
     name: 'test2'
     dir: false
   },
   {
     id: 4,
     uniqueId: '1.2.4',
     name: 'test3'
     dir: true
   }
 ]},
 {
   id: 3,
   uniqueId: '1.3',
   name: 'test23'
   dir: true,
   childs: [
    {
     id: 1,
     uniqueId: '1.3.1',
     name: 'test23'
     dir: true
    }
  ]
}
}]

I can't find a way to convert flat into the desired nested object. I already have a function that returns children of the current object isChild(parent, objectToCheck). I suppose it's better to use some kind of recursion for this but I am totally stuck.

Please help me to convert it into desired nested object.

Any suggestions on other ways to sort flat array are welcome too! Maybe there's a better way to sort it without actually converting back and force?

Thanks a lot in advance!

2
  • Will these array elements always be sorted in the order that we see in the example inputs? Commented Jun 22, 2020 at 18:57
  • @RahulBhobe Yes, I have a sorting function to make it this way. Thanks for asking I'll update my question to mention this Commented Jun 22, 2020 at 19:02

1 Answer 1

1

You could sort the data directly and build a tree with uniqueId and a parent value.

const
    input = [{ id: 1, uniqueId: '1', name: 'folder1', dir: true }, { id: 2, uniqueId: '1.2', name: 'test1', dir: false }, { id: 3, uniqueId: '1.2.3', name: 'test2', dir: false }, { id: 4, uniqueId: '1.2.4', name: 'test3', dir: true }, { id: 3, uniqueId: '1.3', name: 'test23', dir: true }, { id: 1, uniqueId: '1.3.1', name: 'test6', dir: true }],
    tree = function (data) {
        var t = {};
        data.forEach(o => {
            const parent = o.uniqueId.split('.').slice(0, -1).join('.');
            Object.assign(t[o.uniqueId] = t[o.uniqueId] || {}, o);
            t[parent] = t[parent] || {};
            t[parent].children = t[parent].children || [];
            t[parent].children.push(t[o.uniqueId]);
        });
        return t[''].children;
    }(input.sort((a, b) => b.dir - a.dir));
   
console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }

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

3 Comments

Thanks! This would be my second step after converting flat array into nested object. But my problem is that I can't convert flat array into nested object right now.
Thanks a lot. This is a perfect solution! @Nina
The only thing I had to modify was to replace the following line: Object.assign(t[o.uniqueId] = t[o.uniqueId] || {}, o) with t[o.uniqueId] = {...o, childs: t[o.uniqueId] && t[o.uniqueId].childs || []} Because Object.assign overwrites the childs property of the existing object t[o.uniqueId]

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.