2

Having issues writing a javascript sort function that would let me do the following:

UPDATE: this is javascript for node.js

I have a bunch of files and folders as JSON objects with the following properties

[
  {"name":"Folder B","isFolder":true},
  {"name":"File A","isFolder":false},
  {"name":"Folder A","isFolder":true},
  {"name":"File B","isFolder":false}
]

I want to sort this array so the folders are grouped at the top and alphabetically ordered, then files alphabetically ordered like so

[
  {"name":"Folder A","isFolder":true},
  {"name":"Folder B","isFolder":true},
  {"name":"File A","isFolder":false},
  {"name":"File B","isFolder":false}
]

After much researching on stackoverflow here I've come up with this, but it just groups the folders at the top, and does not sort by the name .. thoughts?

array.sort(function(a,b){
    return (b.isFolder-a.isFolder) || (b.name - a.name);
}));
2
  • Have you consider using underscore ? it has a a great sortBy function: sortBy(data, "isFolder") sortBy(data,"name") Commented Nov 27, 2014 at 19:37
  • sorry should have mentioned that this is on node.js .. Commented Nov 27, 2014 at 19:38

4 Answers 4

3

subtracting one string from another will always give "NaN", instead, use localeCompare().

array.sort(function(a,b){
    return (b.isFolder-a.isFolder) || (a.name.toString().localeCompare(b.name));
});

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare

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

2 Comments

oh localeCompare did the trick, however how does this work in node.js exactly?
Unfortunately I've never used node.js so I can't help you there.
1

Your names are no numbers, you cannot get a comparison value by subtracting them. Use

array.sort(function(a,b){
    return (b.isFolder-a.isFolder) || +(a.name>b.name)||-(a.name<b.name);
});

Comments

0

The sort function below first checks to see if the items to be compared are of different types, which is to say that one is a folder and the other is a file. If so, the folder must come first, and the function returns -1. If not, we return 1 because that's what the sort function requires if the second item is to come before the first.

If the items are of the same type, we compare the names. In this case it's possible that the two names are the same, in which case we must return 0.

var array = [                            // Test data.
  {"name":"Folder B","isFolder":true},
  {"name":"File A","isFolder":false},
  {"name":"Folder A","isFolder":true},
  {"name":"File B","isFolder":false}
];

array.sort(function(a, b) {
  if (a.isFolder != b.isFolder) {        // Is one a folder and
     return (a.isFolder ? -1 : 1);       //  the other a file?
  }                                      // If not, compare the
  return a.name.localeCompare(b.name);   //  the names.
});

for (var i = 0; i < array.length; ++i) { // Check the result.
  document.write(array[i].name+' '+array[i].isFolder+'<br />');
}

Comments

0

This is another possible solution;

var objects = [
  {"name":"Folder B","isFolder":true},
  {"name":"File A","isFolder":false},
  {"name":"Folder A","isFolder":true},
  {"name":"File B","isFolder":false}
];

function isFolder(object) {
    return object.isFolder;
}

function isNotFolder(object) {
    return !object.isFolder;
}

function byName(a, b) {
     return a.name.localeCompare(b.name);
}

var folders = objects.filter(isFolder).sort(byName),
    files = objects.filter(isNotFolder).sort(byName);

var allSorted = folders.concat(files);

console.log(allSorted);

Though its way longer than other solutions it is IMHO much more readable.

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.