【问题标题】:Javascript sort and orderJavascript排序和排序
【发布时间】:2019-02-22 21:20:38
【问题描述】:

所以我有这个数组

[ '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'
]

并以上述数组中的以下部分为例:

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

我想像这样排序

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

所以更具体的我想要的是在该数组中找到字符串重复的地方,然后检查末尾是否有 [.cfg.js, .ctrl.js, .module.js] 并自动将它们排序为 [ .module.js、.cfg.js、.ctrl.js]

谁能帮帮我?

【问题讨论】:

    标签: javascript sorting


    【解决方案1】:

    单一排序建议。

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

    为了防止这么多替换,我建议看看sorting with map

    【讨论】:

    • 非常优雅的解决方案。为此+1。不确定性能,但在这样的小情况下,这并不重要。
    • @Nina Scholz,您能否更新您的代码以忽略除“src/app”之外的其余部分; .我只想在那里排序。谢谢
    • 'template ...' 是什么?
    • 请忽略,html 的存储位置,角度 js 中的 $templateCache。
    • 只在'src/app'中排序
    【解决方案2】:

    你可以试试这样的:

    算法:

    1. 根据路径分组并将文件名存储为值。
    2. 检查特殊文件".cfg.js" 之一是否存在
    3. 根据自定义排序对以下列表进行排序。
    4. 循环遍历对象的属性并将键与值连接起来以再次形成完整路径。

    如果您希望对整个数组进行排序,您可以对键本身进行排序,然后将路径与名称合并。我已经做到了。如果您不想这样做,只需从最终循环中删除 sort 函数即可。

    样本

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

    【讨论】:

    • 我认为排序不能正常工作,因为它仍然不能正常排序...... :(
    • 你能再解释一下吗?
    • 好吧,例如我在控制台中得到的 Array[3],我得到的命令是 hekate.cfg,js,hekate.ctrl.js,hekate.module.js 而不是我想要的命令.module.js、.cfg.js、.ctrl.js ... :(
    • 我把 console.log(o[k].indexOf(".cfg.js"));检查后它给了我所有-1。我猜代码似乎有问题?
    • @allocen 是的。你说的对。我已经更新了我的答案。希望对您有所帮助。
    【解决方案3】:

    首先为“hekate”等名称创建一个数组。 然后为最终结果制作一个数组。

    我们需要 3 个用于 ctrls、cfgs 和模块的搜索循环。

    如果字符串包含 arrayWithNames[0] + '.module' 将整个记录推送到您创建的新数组。与 ctrls 和 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
    

    【讨论】:

    • 是的,我也想过这个问题,但是对于 ex,我将拥有 user.ctrl.js、user.cfg.js、user.module.js 并按照你所说的和 hekate 一起做像 -> hekate.module.js,user.module.js,hekate.ctrl.js, user.ctrl.js 等等我不想要,但是 hekate.module.js,hekate.cfg.js,hekate.ctrl .js,user.module.js,user.cfg.js,user.ctrl.js
    • 因此您必须添加另一个数组,其中包含“hekate”等名称。我会在一分钟后在我的答案代码中向你展示这一点
    • 嗯,它给了我未定义的 indexOf ... :|
    • 现在就试试吧。 3 个搜索循环应该可以正常工作。现在您必须在第一个 for 循环中找到所有模块名称(如 hekate)。我希望你能做到这一点
    【解决方案4】:

    您可以向array.sort 提供自己的比较功能(参见https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

    编写一个返回正确顺序的模块、ctrls 和 cfgs:

    应该先去掉后缀,如果其他都一样,用正确的逻辑按照后缀的顺序返回。否则按字母顺序返回值。

    更新

    我没有测试这段代码(还没有完成),但它应该看起来像这样:

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

    更新 2

    这是一个有效的小提琴 (https://jsfiddle.net/d4fmc7ue/)。

    【讨论】:

    • 我之前也看到了,我可以使用它但是...我不知道从哪里开始。
    • 给我一些错误,例如:对象供应商/角度/角度.min.js没有方法'endsWith'
    • 我使用了 endsWith,它是 ES6 的一个函数,所以你可能需要为此使用 polyfill,或者用其他方法替换它,例如 indexOf。但是,您描述的错误可能意味着您没有将数组中的值视为字符串,而是将其视为对象。它应该是一个字符串。
    • 我用正确的代码和一个演示它的小提琴更新了我的答案。
    猜你喜欢
    • 1970-01-01
    • 2018-01-19
    • 2014-11-07
    • 2021-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-31
    • 2021-03-31
    相关资源
    最近更新 更多