1

How can I recursively add a sort key to an infinite hierarchy like this:

[
    {
        "id": "D41F4D3D-EA9C-4A38-A504-4415086EFFF8",
        "name": "A",
        "parent_id": null,
        "sortNr": 1,
        "children": [
            {
                "id": "07E556EE-F66F-49B5-B5E4-54AFC6A4DD9F",
                "name": "A-C",
                "parent_id": "D41F4D3D-EA9C-4A38-A504-4415086EFFF8",
                "sortNr": 3,
                "children": []
            },
            {
                "id": "8C63981E-0D30-4244-94BE-658BAAF40EF3",
                "name": "A-A",
                "parent_id": "D41F4D3D-EA9C-4A38-A504-4415086EFFF8",
                "sortNr": 1,
                "children": [
                    {
                        "id": "0BA32F23-A2CD-4488-8868-40AD5E0D3F09",
                        "name": "A-A-A",
                        "parent_id": "8C63981E-0D30-4244-94BE-658BAAF40EF3",
                        "sortNr": 1,
                        "children": []
                    }
                ]
            },
            {
                "id": "17A07D6E-462F-4983-B308-7D0F6ADC5328",
                "name": "A-B",
                "parent_id": "D41F4D3D-EA9C-4A38-A504-4415086EFFF8",
                "sortNr": 2,
                "children": []
            }
        ]
    },
    {
        "id": "64535599-13F1-474C-98D0-67337562A621",
        "name": "B",
        "parent_id": null,
        "sortNr": 2,
        "children": []
    },
    {
        "id": "1CE38295-B933-4457-BBAB-F1B4A4AFC828",
        "name": "C",
        "parent_id": null,
        "sortNr": 3,
        "children": [
            {
                "id": "D1E02274-33AA-476E-BA31-A4E60438C23F",
                "name": "C-A",
                "parent_id": "1CE38295-B933-4457-BBAB-F1B4A4AFC828",
                "sortNr": 1,
                "children": [
                    {
                        "id": "76A8259C-650D-482B-91CE-D69D379EB759",
                        "name": "C-A-A",
                        "parent_id": "D1E02274-33AA-476E-BA31-A4E60438C23F",
                        "sortNr": 1,
                        "children": []
                    }
                ]
            }
        ]
    }
]

I want to get a sortable index. For example 0000.0001.0003 or 0001.0003 for node A-C.

The function for leadingZeroes is

function fillZeroes (num) {
    var result = ('0000'+num).slice(-4);
    if (num===null){
       return result
    } else {
    return '0000';
    }
}

It should be sorted by sort number in each level of hierarchy, the sort number should be set newly every time, because I want to do rearrangement by setting it 1,5 to insert it between 1 and 2 (later for drag and drop capability). so 1;1,5;2 should become 1;2;3 and can then be translated to a sort-index like above.

I will also need it for indentation and breadcrumb-stuff.

How do I insert the proper sort-index to each object ?

The question is mainly about the recursion part. I am quite new to JavaScript

Thanks a lot

6
  • possible duplicate of stackoverflow.com/questions/26415675/… Commented Nov 20, 2018 at 12:09
  • Can you clarify about 1,5 - you mean that sortNr property could be floating point number? Commented Nov 20, 2018 at 12:29
  • @DaniilAndreyevichBaunov exactly. If there's just support for integers in JSON I would go with 2,4,6 as representations for 1,2,3 and "insert" with odd numbers. Commented Nov 20, 2018 at 12:35
  • @nch68, I see. So, to summarize, as I understand, you want to base your sort index on sortNr property. And also make it dense so that e.g. sortNr of 1, 5, 5.5, 6 within a single level will become something like 0001, 0002, 0003, 0004. Is it correct? Btw, the answer @georg has given is pretty need. Just needs some adjustment for your use case. Commented Nov 20, 2018 at 12:38
  • @DaniilAndreyevichBaunov exactly. Commented Nov 20, 2018 at 12:39

2 Answers 2

1

Based on great answer by @georg. A bit adjusted solution based on sortNr object property. You can run it straight as is with json being your object. The sort index is written into sortOrder property.

// Mutates the given object in-place.
// Assigns sortOrder property to each nested object
const indexJson = (json) => {

  const obj = {children: json};

  const format = (xs) => xs.map(x => pad(x, 4)).join('.');
  const pad = (x, w) => (10 ** w + x).toString().slice(-w);

  const renumber = (obj, path) => {
    obj.path = path;
    obj.sortOrder = format(path);
    obj.children.slice()
      .sort((obj1, obj2) => obj1.sortNr - obj2.sortNr)
      .forEach((c, n) => renumber(c, path.concat(n+1)));
  };

  renumber(obj, []);
};

indexJson(json);

console.log(JSON.stringify(json, null, 2));
Sign up to request clarification or add additional context in comments.

2 Comments

@nch68, please upvote the answer if it is helpful. This works as a thanks here.
I can't because I have less than "15 reputation" :/
1

Basically

let renumber = (obj, path) => {
    obj.path = path
    obj.children.forEach((c, n) => renumber(c, path.concat(n)))
}

renumber({children: yourData}, [])

this creates a path property, which is an array of relative numbers. If you want to format it in a special way, then you can do

obj.path = format(path)

where format is like

let format = xs => xs.map(pad(4)).join(',')

let pad = w => x => (10 ** w + x).toString().slice(-w)

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.