简体   繁体   中英

Sorting array of objects where key is a variable

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;
    });
};

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM