0

I have the following structure:

var arrOfObjects = [
  {
    folder: {id: 2},
    children: []
  },
  {
    file: {id: 3},
    children: []
  },
  {
    file: {id: 4},
    children: []
  },
  {
    folder: {id: 1},
    children: []
  },
];

And I want to sort it using the following function call:

sortArrOfObjects(arrOfObjects, {
  types: [
    ['file']
  ],
  index: 'id',
  order: 'asc'
});
sortArrOfObjects(arrOfObjects, {
  types: [
    ['folder']
  ],
  index: 'id',
  order: 'asc'
});

The output would be sorted array of first files, and then folders, like:

var arrOfObjects = [
  {
    file: {id: 3},
    children: []
  },
  {
    file: {id: 4},
    children: []
  },
  {
    folder: {id: 1},
    children: []
  },
  {
    folder: {id: 2},
    children: []
  },
];

So I have the following function, calling sort() built-in function on the array, and comparing objects where the given key exists, and skips iteration where the key does not exist in one of the comparators. But it doesn't work, it seems to sort in the completely wrong order. What's wrong?

function sortArrayOfObjects(arr, sortBy) {
    arr.sort(function (a, b) {
        var first = '';
        var second = '';
        for (var i = 0; i < sortBy.types.length; i++) {
            switch (sortBy.types[i].length) {
                case 1:
                    if (a[sortBy.types[i][0]] != undefined) {
                        first = a[sortBy.types[i][0]][sortBy.index].toString().toLowerCase();
                    } else {
                        return;
                    }
                    if (b[sortBy.types[i][0]] != undefined) {
                        second = b[sortBy.types[i][0]][sortBy.index].toString().toLowerCase();
                    } else {
                        return;
                    }
                    break;
                case 2:
                    // not implemented yet
                    break;
                default:
                    break;
            }
        }
        if (first > second) {
            return (sortBy.order == 'asc') ? 1 : -1;
        }
        if (first < second) {
            return (sortBy.order == 'asc') ? -1 : 1;
        }
        return 0;
    });
};

1 Answer 1

2

The technique called "decorate-sort-undecorate" makes jobs like this easy:

var arrOfObjects = [
    {
        folder: {id: 2},
        children: []
    },
    {
        file: {id: 3},
        children: []
    },
    {
        file: {id: 4},
        children: []
    },
    {
        folder: {id: 1},
        children: []
    },
];

result = arrOfObjects
    .map(obj => ('file' in obj) ? [1, obj.file.id, obj] : [2, obj.folder.id, obj])
    .sort((a, b) => a[0] - b[0] || a[1] - b[1])
    .map(x => x[2]);


console.log(result)

Basically, we convert our array like [item, item...] to an array [ [sort-keys, item], [sort-keys, item]..., then sort that array and finally pull our items back - in the right order.

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

2 Comments

Hmm, your way needs a newer version of javascript, doesnt it?
Yeah, but only lambda expressions, it's enough to convert them to callbacks in older version. Thanks!

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.