zoukankan      html  css  js  c++  java
  • Array.prototype.sort():从一道面试题说起

    前几天看一道面试题,要求根据num对下面的对象倒序排序。

    var arr = [
        {name:'A',num:4},
        {name:'G',num:3},
        {name:'V',num:5},
        {name:'A',num:2},
        {name:'X',num:9},
        {name:'R',num:6},
        {name:'N',num:undefined},
    ];

    对于对象按照属性排序 MDN-Array.sort() 上有介绍。下面是MDN上的栗子。

    var items = [
      { name: 'Edward', value: 21 },
      { name: 'Sharpe', value: 37 },
      { name: 'And', value: 45 },
      { name: 'The', value: -12 },
      { name: 'Magnetic' },
      { name: 'Zeros', value: 37 }
    ];
    
    items.sort(function (a, b) {
      if (a.value > b.value) {
        return 1;
      }
      if (a.value < b.value) {
        return -1;
      }
      // a 必须等于 b
      return 0;
    });

     

    于是我们可以简单地写出答案:

    arr.sort(function(){
        return b.num - a.num;
    });

    我对数组中含有undefined时的排序情况有不小的疑惑。

    当num的值全部是正常数字时, arr将会被正常倒序排序,那么在有特殊值的情况下将如何排序呢。这里分别测试了两种情况。

    • num的值为undefined

        

        在完成正常数值的倒序排序后,num值为undefined的对象被放到了最后。后来改成正序测试undefined仍然被放到了最后。

    • num的值未定义(在这里我将题中的num:undefined直接删去)

        

        不管正序还是倒序,num值未定义的对象依然被扔在最后。

     为了查看其排序原理,我们用一个简单的数组模拟一下来看看每一次排序后数组的变化。(正序)

    var arr = [4, 3, 5, 2, undefined, 9 ,6 ];
    function compare(a, b) {
        console.log(a, b, arr);
        return a - b;
    }
    arr.sort(compare);

     控制台结果:

     

    undefined在第一次排序前就被扔到了后面,但对比一下原数组: [4, 3, 5, 2, undefined, 9 ,6 ]  >> [4, 3, 5, 2, 6, 9, undefined]

    发现undefined与数组的最后一位做了交换。实际上我们的compare()函数压根没有将undefined列入考虑范围,而是遇到直接扔到数组最后再进行排序。num值未定义的时候也同理。

    了解了undefined的情况,我们来看一下正常情况下的排序机制。

      第一次:  4大于3,两者交换位置 [3, 4, 5, 2, 6 ,9],看起来像是运用了冒泡排序。

      第二次:  4小于5,没有位置交换 [3, 4, 5, 2, 6 ,9]

      第三次:  5大于2,在这里仅仅是5覆盖了2的位置得到 [3, 4, 5, 5, 6, 9]

      第四次:  4大于2,4又覆盖了5的位置得到 [3, 4, 4, 5, 6, 9]

      第五次:  3大于2,这时2出现得到 [2, 3, 4, 5, 6, 9]

      第六次:  5小于6,位置不变,第七次同。

      最终得到正序排序结果。

    上述的排序过程中只有第一次做了一次交换,再看第三四五次都与2做了比较并且有移位的过程。这与插入排序的过程类似。但是第一次不能确定是用了冒泡还是插入排序。

    实际上第一次也同样使用了插入排序。假设确实是冒泡,那么第一次排序会将两两相邻的数一直比较至数列尽头(第二次倒着往前比较)。不能把一次交换就简单认为是冒泡排序。

    使用冒泡的第一次排序后顺序应该是 [3, 4, 2, 5, 6, 9].

    换一组数再来测验一下  var arr = [4, 3, 1, 2, -1];

    可以得出结论sort()函数主要运用了简单插入排序算法。下面是我偷来的图解释了插入排序的动态过程。

     注:上面的测试全部在chrome环境下实现,不同的浏览器使用的排序机制可能不同。

  • 相关阅读:
    java第19次
    Unity3D常用的生命周期函数
    Unity3D结合ZXing生成中间带图标的二维码并保存
    Unity查看当前内存使用情况(针对移动端开发)
    Unity 获取鼠标悬停位置下的UI或3D物体对象
    【Unity3D】获取鼠标在三维空间(世界坐标系)的位置
    【Unity3D—C#】按下任意按键,返回按键的名称 以及 KeyCode键码详解
    Unity UGUI获取鼠标在屏幕的准确点击位置
    ML-Agent:通过TF#使用训练完成的模型数据
    对《ml-agent:Win10下环境安装》更新
  • 原文地址:https://www.cnblogs.com/qimeng/p/6916576.html
Copyright © 2011-2022 走看看