Skip to content
Advertisement

how to sort recursively in JS

I’m trying to sort an Array type data recursively.

Here’s the data structure.

const DATA = [
  {
    id: 123,
    name: "kevin",
    children: [
      {
        id: 345,
        name: "luke",
        children: [
          {
            id: 67895,
            name: "jane",
            children: [{ id: 556, name: "che", children: [] }]
          },
          {
            id: 89760,
            name: "kendrick",
            children: [
              { id: 4627, name: "auro", children: [] },
              { id: 777, name: "civil", children: [] },
              { id: 37654, name: "hobbit", children: [] }
            ]
          }
        ]
      },
      { id: 123215, name: "ron", children: [] }
    ]
  },
  { id: 7642, name: "dobby", children: [] },
  { id: 2589, name: "porter", children: [] }
];

I wanna sort by either ‘id’ or ‘name’.

This is what I tried.

const sorting = (array, label, sortedBy) => {
  if (sortedBy === "asc")
    return array.sort((a, b) => (a[label] > b[label] ? 1 : -1));
  return array.sort((a, b) => (b[label] > a[label] ? 1 : -1));
};

const sortingData = (data, label, sort) => {
  let result;

  for (let i = 0; i < data.length; i++) {
    result = sorting(data, label, sort);
    if (data[i].children && data[i].children.length) {
      result[i].children = sortingData(data[i].children, label, sort);
    }
  }

  return result;
};

// Sample data
const DATA = [
  {
    id: 123,
    name: "kevin",
    children: [
      {
        id: 345,
        name: "luke",
        children: [
          {
            id: 67895,
            name: "jane",
            children: [{ id: 556, name: "che", children: [] }]
          },
          {
            id: 89760,
            name: "kendrick",
            children: [
              { id: 4627, name: "auro", children: [] },
              { id: 777, name: "civil", children: [] },
              { id: 37654, name: "hobbit", children: [] }
            ]
          }
        ]
      },
      { id: 123215, name: "ron", children: [] }
    ]
  },
  { id: 7642, name: "dobby", children: [] },
  { id: 2589, name: "porter", children: [] }
];

const data = sortingData(DATA, "id", "asc");

console.log(data);

In my poor logic, it seems working but not properly working. Because item’s children or children’s children is not sorted. 🙁

What should I fix? or maybe my approach was totally wrong?

Thank you so much for your help.

below is what I wanted:

const DATA = [
  {
    id: 123,
    name: "kevin",
    children: [
      {
        id: 345,
        name: "luke",
        children: [
          {
            id: 67895,
            name: "jane",
            children: [{ id: 556, name: "che", children: [] }]
          },
          {
            id: 89760,
            name: "kendrick",
            children: [
              { id: 777, name: "civil", children: [] },
              { id: 4627, name: "auro", children: [] },
              { id: 37654, name: "hobbit", children: [] }
            ]
          }
        ]
      },
      { id: 123215, name: "ron", children: [] }
    ]
  },
  { id: 2589, name: "porter", children: [] },
  { id: 7642, name: "dobby", children: [] }
];

Advertisement

Answer

Basically you can change the order of a and b sort params depending on the order param you pass to your custom function. Then also based on the type of current param (string or number) you use different types of sort method.

const DATA = [{"id":123,"name":"kevin","children":[{"id":345,"name":"luke","children":[{"id":67895,"name":"jane","children":[{"id":556,"name":"che","children":[]}]},{"id":89760,"name":"kendrick","children":[{"id":4627,"name":"auro","children":[]},{"id":777,"name":"civil","children":[]},{"id":37654,"name":"hobbit","children":[]}]}]},{"id":123215,"name":"ron","children":[]}]},{"id":7642,"name":"dobby","children":[]},{"id":2589,"name":"porter","children":[]}]

function sortData(data, label, order) {
  data.sort((a, b) => {
    const x = order === 'asc' ? a : b;
    const y = order === 'asc' ? b : a;

    if ([x[label], y[label]].some(e => typeof e === 'string')) {
      return x[label].localeCompare(y[label])
    } else {
      return x[label] - y[label]
    }
  })

  data.forEach(el => {
    if (el.children) {
      sortData(el.children, label, order)
    }
  })
}

sortData(DATA, 'name', 'desc')

console.log(JSON.stringify(DATA, 0, 4))
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement