zoukankan      html  css  js  c++  java
  • 我可能不懂Array.prototype.sort

    今天 fix 我们后台系统的一些 bug。系统是基于 beego 和模板开发的,各种前后端代码揉作一团,没有格式,没有 eslint,全局变量满天飞,连 js 代码都有后端的插值,读起来非常 酸爽

    我耐着性子看了半天,陆陆续续改了几个 bug,顺便整理一下代码,总算完成的差不多了。只剩下最后一个小问题,乐观估计可以十分钟内搞定。想到这里,我不禁激动地哼起了小曲儿,马上要从酸爽的代码中抽身了。然而,十分钟过去了,半个小时过去了。。

    这事还真没那么简单,事情要从我自以为‘熟悉’的 Array.prototype.sort 这个方法说起。

    根据 MDN 的文档,这个方法接收一个可选的 compareFunction。而这个 compareFunction 接收两个数组元素,并返回一个值决定这两个元素是否需要调换位置,规则如下:

    如果 compareFunction(a, b) 小于 0 ,那么 a 会被排列到 b 之前;
    如果 compareFunction(a, b) 等于 0 , a 和 b 的相对位置不变。备注: ECMAScript 标准并不保证这一行为,而且也不是所有浏览器都会遵守(例如 Mozilla 在 2003 年之前的版本);
    如果 compareFunction(a, b) 大于 0 , b 会被排列到 a 之前。
    compareFunction(a, b) 必须总是对相同的输入返回相同的比较结果,否则排序的结果将是不确定的。

    知道这个规则之后,我们就可以愉快的对数组按自己规则来进行排序了,普通的升序或者降序自然没的说,然而我面对的是这么一个自定义规则:

    有一个数组,由一位数,两位数和 3 位数构成;现在需要排序后的数组按整体从小到大排列,但是两位数的元素要放到最后。举个例子:

    function compare(a,b){
     // TODO
    }
    
    let arr = [1, 8, 3, 11, 100, 15, 201]
    
    arr.sort(compare)
    
    arr //[1, 3, 8, 100, 201, 11, 15]
    
    

    到了这里,大家可以先尝试写一下这个 compare 函数;如果能成功输出正确的结果,那么这篇文章对你也就没什么用了。在说答案之前,先说一个我之前理解存在的误区:

    compare 函数接收到的两个元素在数组中的位置是不是一定 a 在前面,b 在后面?其实不是。在 compare 函数中打印出 a 和 b 就可以发现这一点。

    自定义排序

    知道 a 和 b 是无序的之后,我们就可以尝试写一下这个比较函数了,传入的元素可以分为以下 3 种情况:

    1. a,b 都是两位数时,按从小到大排序
    2. a,b 中有一个两位数,两位数放到后边
    3. a,b 都不是两位数,按从小到大排序

    所以,代码如下:

    function isdoubleDigit(num){ return num >= 10 && num <= 99 }
    function compare(a, b){
        // 都是两位数
    	if(isdoubleDigit(a) && isdoubleDigit(b)) {
          return a - b
        }
        
        // a是两位数,b不是,a应该被放到最后
        if(isdoubleDigit(a) && !isdoubleDigit(b)) {
          return 1
        }
        
        // b是两位数,a不是,b应该被放到最后
        if(!isdoubleDigit(a) && isdoubleDigit(b)) {
          return -1
        }
        // 都不是两位数,正常排序
        return a - b
    }
    
    

    这里说一下我原先理解中的第二个误区,那就是以为, compareFunction是用来交换a,b元素在数组中的位置的,像冒泡排序那样。其实这种看法是错误的,看下面的截图可以看出,compareFunction只是在决定排序后的数组中a,b的相对顺序,而不是对a,b的位置直接进行交换。
    paixu.png

    如MDN中所说,sort方法是用原地算法实现的,有兴趣的朋友可以去研究一下,本文完。

  • 相关阅读:
    .NET开发不可不知、不可不用的辅助类(一)
    .NET开发不可不知、不可不用的辅助类(三)(报表导出终结版)
    如何获取类或属性的自定义特性(Attribute)
    如何使用C#进行Visio二次开发
    列表查询组件代码, 简化拼接条件SQL语句的麻烦
    强大的模板引擎开源软件NVelocity
    自己编写的操作实体类的分页控件, 实现页码层与数据库的具体的信息隔离
    代码生成工具随笔(1) 关于代码生成器
    老歌新唱使用VB6开发的ActiveX实现.NET程序的混淆加密
    VB6中如何使用C#开发的WebService进行开发
  • 原文地址:https://www.cnblogs.com/imgss/p/sort.html
Copyright © 2011-2022 走看看