5

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?

4 Answers 4

5

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.

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

9 Comments

Very elegant solution. +1 for that. Not sure about performance, however in small cases like this it doesn't really matter.
@Nina Scholz, could you please update your code to ignore the rest except 'src/app'; . I want the sorting only there. Thanks
what is with 'template ...'?
Ignore that too, please, is where the html will be stored, $templateCache in angular js.
Only sort in 'src/app'
|
2

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

8 Comments

I think that sort doesnt work as it should because it still doesn't sort like it should... :(
Can you explain a little more?
Well, for example the Array[3] that i get in console, i get the order hekate.cfg,js,hekate.ctrl.js,hekate.module.js and not the order i want .module.js, .cfg.js, .ctrl.js ... :(
In for i putted console.log(o[k].indexOf(".cfg.js")); and after checking it gives me all -1. Seems there is something wrong with the code, i guess?
@allocen Yes. You are right. I have updated my answer. Hope it helps.
|
0

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

4 Comments

Yeah i thought about that too but for ex, i will have user.ctrl.js,user.cfg.js,user.module.js and doing what you said in addition with hekate it will be like -> hekate.module.js,user.module.js,hekate.ctrl.js, user.ctrl.js and so on which i dont want, but hekate.module.js,hekate.cfg.js,hekate.ctrl.js,user.module.js,user.cfg.js,user.ctrl.js
so you have to add another array that will contains names like 'hekate'. I'll show you that in my answer code in a minute
Hmm somehow it gives me indexOf of undefined... :|
try it now. The 3 searching loops should work correctly. Now you have to find all module names (like hekate) in first for loop. I hope you can do this
0

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.

4 Comments

I saw that earlier too, i could use it but... i have no ideea yet where to start.
Gives me some errors like: Object vendor/angular/angular.min.js has no method 'endsWith'
I used endsWith which is a function of ES6, so you might need to use a polyfill for that, or replace it with some other method like indexOf. However, the error you describe might mean that you are not treating the value in the array like string but like an object. It suppose to be a string.
I updated my answer with correct code and a fiddle that demonstrate it.

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.