allocen allocen - 7 months ago 33
Javascript Question

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?

Answer

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

Comments