简体   繁体   中英

Javascript sort and order

So i have this array

[ 'vendor/angular/angular.min.js',
  'vendor/angular-nice-bar/dist/js/angular-nice-bar.min.js',
  'vendor/angular-material/modules/js/core/core.min.js',
  'vendor/angular-material/modules/js/backdrop/backdrop.min.js',
  'vendor/angular-material/modules/js/dialog/dialog.min.js',
  'vendor/angular-material/modules/js/button/button.min.js',
  'vendor/angular-material/modules/js/icon/icon.min.js',
  'vendor/angular-material/modules/js/tabs/tabs.min.js',
  'vendor/angular-material/modules/js/content/content.min.js',
  'vendor/angular-material/modules/js/toolbar/toolbar.min.js',
  'vendor/angular-material/modules/js/input/input.min.js',
  'vendor/angular-material/modules/js/divider/divider.min.js',
  'vendor/angular-material/modules/js/menu/menu.min.js',
  'vendor/angular-material/modules/js/select/select.min.js',
  'vendor/angular-material/modules/js/radioButton/radioButton.min.js',
  'vendor/angular-material/modules/js/checkbox/checkbox.min.js',
  'vendor/angular-material/modules/js/switch/switch.min.js',
  'vendor/angular-material/modules/js/tooltip/tooltip.min.js',
  'vendor/angular-material/modules/js/toast/toast.min.js',
  'vendor/angular-clipboard/angular-clipboard.js',
  'vendor/angular-animate/angular-animate.min.js',
  'vendor/angular-aria/angular-aria.min.js',
  'vendor/angular-messages/angular-messages.min.js',
  'vendor/angular-ui-router/release/angular-ui-router.js',
  'src/app/about/about.js',
  'src/app/hekate.cfg.js',
  'src/app/hekate.ctrl.js',
  'src/app/hekate.module.js',
  'src/app/home/home.js',
  'src/app/user/dialog/user.signIn.ctrl.js',
  'src/app/user/dialog/user.signIn.module.js',
  'src/app/user/user.cfg.js',
  'src/app/user/user.ctrl.js',
  'src/app/user/user.module.js',
  'src/common/services/toast.service.js',
  'templates-common.js',
  'templates-app.js'
]

And taking the following part from the above array as example:

[ 
  'src/app/hekate.cfg.js',
  'src/app/hekate.ctrl.js',
  'src/app/hekate.module.js',
]

I want to sort it like

[ 
  'src/app/hekate.module.js',
  'src/app/hekate.cfg.js',
  'src/app/hekate.ctrl.js',
]

So more specific of what i want is to find in that array where string is duplicated and after check if has at the end [.cfg.js, .ctrl.js, .module.js] and automatic order them to [.module.js, .cfg.js, .ctrl.js]

Can anyone please help me with that?

A single sort proposal.

 var array = ['src/app/about/about.js', 'src/app/hekate.cfg.js', 'src/app/hekate.ctrl.js', 'src/app/hekate.module.js', 'src/app/home/home.js', 'src/app/user/dialog/user.signIn.ctrl.js', 'src/app/user/dialog/user.signIn.module.js', 'src/app/user/user.cfg.js', 'src/app/user/user.ctrl.js', 'src/app/user/user.module.js']; array.sort(function (a, b) { function replaceCB(r, a, i) { return r.replace(a, i); } var replace = ['.module.js', '.cfg.js', '.ctrl.js']; return replace.reduce(replaceCB, a).localeCompare(replace.reduce(replaceCB, b)); }); document.write('<pre>' + JSON.stringify(array, 0, 4) + '</pre>'); 

To prevent so much replaces, i suggest to have a look to sorting with map .

You can try something like this:

Algo:

  1. Group based on path and store file names as value.
  2. Check for existence of one of special file ".cfg.js"
  3. Sort following list based on custom sort.
  4. Loop over object's property and join key with values to form full path again.

If you wish to sort full array, you can sort keys itself and then merge path with names. I have done this. If you do not wish to do this, just remove sort function from final loop.

Sample

 var data=["vendor/angular/angular.min.js","vendor/angular-nice-bar/dist/js/angular-nice-bar.min.js","vendor/angular-material/modules/js/core/core.min.js","vendor/angular-material/modules/js/backdrop/backdrop.min.js","vendor/angular-material/modules/js/dialog/dialog.min.js","vendor/angular-material/modules/js/button/button.min.js","vendor/angular-material/modules/js/icon/icon.min.js","vendor/angular-material/modules/js/tabs/tabs.min.js","vendor/angular-material/modules/js/content/content.min.js","vendor/angular-material/modules/js/toolbar/toolbar.min.js","vendor/angular-material/modules/js/input/input.min.js","vendor/angular-material/modules/js/divider/divider.min.js","vendor/angular-material/modules/js/menu/menu.min.js","vendor/angular-material/modules/js/select/select.min.js","vendor/angular-material/modules/js/radioButton/radioButton.min.js","vendor/angular-material/modules/js/checkbox/checkbox.min.js","vendor/angular-material/modules/js/switch/switch.min.js","vendor/angular-material/modules/js/tooltip/tooltip.min.js","vendor/angular-material/modules/js/toast/toast.min.js","vendor/angular-clipboard/angular-clipboard.js","vendor/angular-animate/angular-animate.min.js","vendor/angular-aria/angular-aria.min.js","vendor/angular-messages/angular-messages.min.js","vendor/angular-ui-router/release/angular-ui-router.js","src/app/about/about.js","src/app/hekate.cfg.js","src/app/hekate.ctrl.js","src/app/hekate.module.js","src/app/home/home.js","src/app/user/dialog/user.signIn.ctrl.js","src/app/user/dialog/user.signIn.module.js","src/app/user/user.cfg.js","src/app/user/user.ctrl.js","src/app/user/user.module.js","src/common/services/toast.service.js","templates-common.js","templates-app.js"]; // Create groups based on path var o = {}; data.forEach(function(item) { var lastIndex = item.lastIndexOf('/') + 1; var path = item.substring(0, lastIndex); var fname = item.substring(lastIndex); if (!o[path]) o[path] = []; o[path].push(fname); }); var manualOrder= [".module.js", ".cfg.js", ".ctrl.js"]; Array.prototype.fuzzyMatch = function(search){ return this.some(function(item){ return item.indexOf(search)>-1; }); } Array.prototype.fuzzySearchIndex = function(search){ var pos = -1; this.forEach(function(item, index){ if(search.indexOf(item)>-1){ pos = index; } }); return pos; } function myCustomSort(a,b){ var a_pos = manualOrder.fuzzySearchIndex(a); var b_pos = manualOrder.fuzzySearchIndex(b); return a_pos > b_pos ? 1 : a_pos < b_pos ? -1 : 0; } // Check for ".cfg.js" and apply custom sort for (var k in o) { if (o[k].fuzzyMatch(".cfg.js")) { o[k].sort(myCustomSort); } } // Merge Path and names to create final value var final = []; Object.keys(o).sort().forEach(function(item) { if (Array.isArray(o[item])) { final = final.concat(o[item].map(function(fn) { return item + fn })); } else final = final.concat(o[item]); }); console.log(final); 

First make an array for names like 'hekate'. Then make an array for final results.

We need 3 searching loops for ctrls, cfgs and modules.

If string contains arrayWithNames[0] + '.module' push the whole record to new array that you created. Same with ctrls and cfgs.

var allItems = []; //your array with all elements
var namesArray = [];
var finalResultsArray = [];

//fill name array here:
for(var i=0; i<=allItems.length; i++){
    //you have to split string and find the module name (like 'hekate'). i hope you know how to split strings
}

//sort by modules, cfgs, ctrls:
for(var i=0; i<=namesArray.length; i++){
    if(allItems[i].indexOf(namesArray[i] + '.module') > -1) {
        finalResultsArray.push(allItems[i]);
    }
}
for(var i=0; i<=namesArray.length; i++){
    if(allItems[i].indexOf(namesArray[i] + '.cfg') > -1) {
        finalResultsArray.push(allItems[i]);
    }
}
for(var i=0; i<=namesArray.length; i++){
    if(allItems[i].indexOf(namesArray[i] + '.ctrl') > -1) {
        finalResultsArray.push(allItems[i]);
    }
}

//now finalResultsArray have what you wanted

You can provide your own compare function to array.sort (see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort )

Write one that returns the correct order for modules, ctrls and cfgs:

It should first remove the suffixes, and if the rest is the same, use the correct logic to return the order according to the suffix. Otherwise return a value according to the alphabetical order.

Update

I didn't test this code (not is it finished), but it should look something like that:

arr.sort(function(a, b) {
  if ((a.endsWith(".cfg.js") || a.endsWith(".ctrl.js") || a.endsWith(".module.js")) &&
    (b.endsWith(".cfg.js") || b.endsWith(".ctrl.js") || b.endsWith(".module.js"))) {

    var sortedSuffixes = {
      ".module.js": 0,
      ".cfg.js": 1,
      ".ctrl.js": 2
    };

    var suffixAIdx = a.lastIndexOf(".cfg.js");
    if (suffixAIdx < 0)  suffixAIdx = a.lastIndexOf(".ctrl.js");
    if (suffixAIdx < 0) suffixAIdx = a.lastIndexOf(".module.js");

    var suffixBIdx = b.lastIndexOf(".cfg.js");
    if (suffixBIdx < 0)  suffixBIdx = b.lastIndexOf(".ctrl.js");
    if (suffixBIdx < 0) suffixBIdx = b.lastIndexOf(".module.js");

    var prefixA = a.substring(0, suffixAIdx);
    var prefixB = b.substring(0, suffixAIdx);

    if (prefixA != prefixB)
    {
        return a.localeCompare(b);
    }

    var suffixA = a.substring(suffixAIdx);
    var suffixB = b.substring(suffixBIdx);

    return sortedSuffixes[suffixA] - sortedSuffixes[suffixB];
  } else {
    return a.localeCompare(b);
  }
});

Update 2

Here is a fiddle ( https://jsfiddle.net/d4fmc7ue/ ) that works.

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