1

i got some sort of an issue with my custom sorting. So, basically i have this array:

[ 'src/app/account/account.js',
  'src/app/account/dashboard/characters/characters.js',
  'src/app/account/dashboard/characters/detail/detail.js',
  'src/app/account/dashboard/dashboard.ctrl.js',
  'src/app/account/dashboard/dashboard.js',
  'src/app/account/dashboard/panels/admin.ctrl.js',
  'src/app/account/dashboard/panels/users.ctrl.js',
  'src/app/account/donate/donate.ctrl.js',
  'src/app/account/donate/donate.js',
  'src/app/account/settings/settings.ctrl.js',
  'src/app/account/settings/settings.js',
  'src/app/account/vote/vote.ctrl.js',
  'src/app/account/vote/vote.js',
  'src/app/membership/dialogs/login.ctrl.js',
  'src/app/membership/dialogs/register.ctrl.js',
  'src/app/membership/dialogs/termsOfService.ctrl.js',
  'src/app/membership/membership.ctrl.js',
  'src/app/membership/membership.module.js',
  'src/app/news/news.ctrl.js',
  'src/app/news/news.js',
  'src/app/noctis.ctrl.js',
  'src/app/noctis.js',
  'src/app/widgets/playersOnline/playersOnline.js',
  'src/app/widgets/rankings/rankings.js',
  'src/app/widgets/serverDetails/serverDetails.js',
  'src/common/directives/feeds/feeds.js',
  'src/common/directives/panel/panel.js' ]

And what i would like that after the src/app/ the very first js that comes after the very first folder after src/app/ in our case: account, membership(can be more custom names) to be loaded first, like in the next example:

  ['src/app/membership/membership.module.js',
  'src/app/membership/membership.ctrl.js',
  'src/app/membership/dialogs/login.ctrl.js',
  'src/app/membership/dialogs/register.ctrl.js',
  'src/app/membership/dialogs/termsOfService.ctrl.js',]

Can you guys help me with some code for my needs? src/app will always be a fixed name except of the next directory that comes after src/app/.

Basically what comes after the unknown name of the directory after src/app, the sub directories in our case(dialogs) or can be something else like(detail, detail/character), to be loaded latest no matter what.

Basically this is the whole function:

function sortJSFiles(files) {
        var src = [];
        var vendor = [];
        files.forEach(function(item) {
            if (item.startsWith('src')) {
                src.push(item);
            } else {
                vendor.push(item);
            }
        });

        src.sort(function(a, b) {
            var replace = ['noctis.js', 'noctis.ctrl.js', '.module.js', '.ctrl.js'];

            function replaceCB(previousValue, currentValue, currentIndex, array) {
                return previousValue.replace(currentValue, currentIndex);
            }
            return replace.reduce(replaceCB, a).localeCompare(replace.reduce(replaceCB, b));
        });
        return vendor.concat(src);
    }

What it does, is that in paramater files comes a lot of paths with js files and i'm trying to sort them after my rule. The problem is, for example taking membership example:

  ['src/app/membership/dialogs/login.ctrl.js',
  'src/app/membership/dialogs/register.ctrl.js',
  'src/app/membership/dialogs/termsOfService.ctrl.js',
  'src/app/membership/membership.module.js',
  'src/app/membership/membership.ctrl.js']

It succesffully change the sort like loading *.js files that starts first with .module.js and than with .ctrl.js but there is a problem in my code that i need that any js file that comes after src/app/somefolder to be loaded first and any subfolders that are in that somefolder to be loaded latest no matter what.

9
  • Yes, it's possible. Was that your question? Commented Oct 1, 2016 at 15:45
  • No, sorry, I forgot to add that i need that piece of code for that. Thank you nicely. Commented Oct 1, 2016 at 15:46
  • 1
    Why haven't you tried doing it? You have the requirements, it all seems pretty clear and it should be pretty simple. Commented Oct 1, 2016 at 15:48
  • Coding requests are off-topic for SO. You'll need to do some work and show us where you got stuck. Commented Oct 1, 2016 at 15:51
  • 1
    You should post what you tried with, and show what results it gave (or error). Commented Oct 1, 2016 at 16:26

1 Answer 1

1

I am not sure I understood you correctly (it would have been nice if you would have added the literal expected output for your sample data).

I think you want to have the folders sorted, but within the same folder, you want the files in there to be sorted before any of the subfolders in that same folder. And this should be true at every nested level.

To get the files sorted first in every folder, you should in fact extract the folders only, and sort those, and only when two items have exactly the same folder sequence, sort by the file name.

This you can do as follows:

src = src.map(function (path) {
    var i = path.lastIndexOf('/');
    return [path.substr(0, i), path.substr(i)];
}).sort(function (a, b) {
    var i = +(a[0] == b[0]);
    return  a[i].localeCompare(b[i]);
}).map(function (pair) {
    return pair[0] + pair[1];
});

var src = [ 'src/app/account/account.js',
  'src/app/account/dashboard/characters/characters.js',
  'src/app/account/dashboard/characters/detail/detail.js',
  'src/app/account/dashboard/dashboard.ctrl.js',
  'src/app/account/dashboard/dashboard.js',
  'src/app/account/dashboard/panels/admin.ctrl.js',
  'src/app/account/dashboard/panels/users.ctrl.js',
  'src/app/account/donate/donate.ctrl.js',
  'src/app/account/donate/donate.js',
  'src/app/account/settings/settings.ctrl.js',
  'src/app/account/settings/settings.js',
  'src/app/account/vote/vote.ctrl.js',
  'src/app/account/vote/vote.js',
  'src/app/membership/dialogs/login.ctrl.js',
  'src/app/membership/dialogs/register.ctrl.js',
  'src/app/membership/dialogs/termsOfService.ctrl.js',
  'src/app/membership/membership.ctrl.js',
  'src/app/membership/membership.module.js',
  'src/app/news/news.ctrl.js',
  'src/app/news/news.js',
  'src/app/noctis.ctrl.js',
  'src/app/noctis.js',
  'src/app/widgets/playersOnline/playersOnline.js',
  'src/app/widgets/rankings/rankings.js',
  'src/app/widgets/serverDetails/serverDetails.js',
  'src/common/directives/feeds/feeds.js',
  'src/common/directives/panel/panel.js' ];

src = src.map(function (path) {
    var i = path.lastIndexOf('/');
    return [path.substr(0, i), path.substr(i)];
}).sort(function (a, b) {
    var i = +(a[0] == b[0]);
    return  a[i].localeCompare(b[i]);
}).map(function (pair) {
    return pair[0] + pair[1];
});

console.log(src);

Explanation of the sort callback function

The sort callback function will receive argument a and b. Each of them is a pair including a path at index 0, and a filename at index 1.

The callback uses a variable i that is intended to get the value 0 or 1. If the paths of a and b are the same, then i will be 1, else it will be 0. It determines whether a comparison is needed on the paths or on the filenames.

The unitary + is used to convert the boolean expression a[0] == b[0] to a number. The conversion is: true=>1, false=>0.

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

7 Comments

Seems to work. Thanks. Can this function be reduced for more peformance boost?
I think this code is quite performant as it is. Do you ask this because you have bad performance with it?
Seems not so far, but hope you don't mind, i've modified the code inside the sort function to sort them after my specific order like ".module.js", ".ctrl.js" and it works as i wanted to. Anyway, many thanks for helping mine.
that converts a boolean (comparison) to number with an unary +. the result is either 0 or 1.
I added an explanation in my answer.
|

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.