在javascript中排序未定义的值无法正常工作

时间:2018-03-02 03:16:34

标签: javascript google-chrome sorting

我有一个像这样的对象数组:

var arr = [{index: 1, key: undefined}, {index: 2, key: undefined},{index: 3, key: undefined},{index: 4, key: undefined},{index: 5, key: undefined},{index: 6, key: undefined},{index: 7, key: undefined},{index: 8, key: undefined},{index: 9, key: undefined},{index: 10, key: undefined},{index: 11, key: undefined},{index: 12, key: undefined},{index: 13, key: undefined},{index: 14, key: undefined},{index: 15, key: undefined},{index: 16, key: undefined},{index: 17, key: undefined},{index: 18, key: undefined},{index: 19, key: undefined} ]

我想按键排序数组arr - 这是所有未定义的值。返回值应与arr相同。但是当我执行时:

arr.sort(function(a,b){return a.key - b.key})

结果与我预期的不一样,数组顺序发生了变化。对这个问题有什么想法吗?

我的结果:https://imgur.com/a/4NyDq

更新:使用其他阵列进行测试:

var b = [{index: 1, key: 10}, {index: 2, key: 10},{index: 3, key: 10},{index: 4, key: 10},{index: 5, key: 10},{index: 6, key: 10},{index: 7, key: 10},{index: 8, key: 10},{index: 9, key: 10},{index: 10, key: 10},{index: 11, key: 10},{index: 12, key: 10},{index: 13, key: 10},{index: 14, key: 10},{index: 15, key: 10},{index: 16, key: 10},{index: 17, key: 10},{index: 18, key: 10},{index: 19, key: 10} ]

每个键都有相同的值,但是当调用sort函数时:https://imgur.com/a/I7kiI

IE和Firefox工作正常,问题发生在Chrome中。 我猜这个案例返回0会出错。

3 个答案:

答案 0 :(得分:2)

问题与array.sort实现中使用的算法的稳定性有关,这取决于用于执行javascript代码的引擎。

Chrome使用Google’s V8 engine。 V8的排序算法使用插入排序快速排序的组合。检查实际的实施here

当数组较小(array.length <= 10)时使用

插入排序,否则使用快速排序。第二种排序算法不稳定,不保证保留等效元素的顺序。

作为结论,我包括两个测试(都使用你的初始比较函数)。 Chrome的结果:

  • 第一个排序是在10个元素数组上执行的(因此保留原始顺序)
  • 对原始数组执行第二次排序,包含19个元素(在这种情况下,保留原始顺序并不确定,这就是更改数组顺序的原因)

const small = [
  {index: 1, key: undefined}, 
  {index: 2, key: undefined},
  {index: 3, key: undefined},
  {index: 4, key: undefined},
  {index: 5, key: undefined},
  {index: 6, key: undefined},
  {index: 7, key: undefined},
  {index: 8, key: undefined},
  {index: 9, key: undefined},
  {index: 10, key: undefined}
];

// stable sort
small.sort(function(a,b){return a.key - b.key});
console.log(small);

var arr = [
  ...small,
  {index: 11, key: undefined},
  {index: 12, key: undefined},
  {index: 13, key: undefined},
  {index: 14, key: undefined},
  {index: 15, key: undefined},
  {index: 16, key: undefined},
  {index: 17, key: undefined},
  {index: 18, key: undefined},
  {index: 19, key: undefined}
];

// unstable sort
arr.sort(function(a,b){return a.key - b.key});
console.log(arr);

可能您需要实现稳定的排序算法,以确保您的代码在执行环境的情况下表现相同。 最常见的稳定算法是bubble-sortinsertion-sortmerge-sort

详细了解stability in sorting algorithms

检查铬虫:V8 doesn't stable sort

Javascript enginesMore

答案 1 :(得分:1)

您要做的是从undefined中减去undefined,结果为NaN

NaN < 0
> false

NaN > 0
> false

NaN -1 1也不是0,并且它不大于0,因此它似乎被视为Firefox

我不确定上述句子是否属实。

根据MDN

  

如果compareFunction(a,b)返回0,则保持a和b相对于彼此保持不变,但是对所有不同的元素进行排序。 注意:ECMAscript标准不保证这种行为,因此并非所有浏览器(例如可追溯到至少2003年的Mozilla版本)都尊重这一点。

所以我在Chrome中对此进行了测试,订单保持不变。但是在x = image.load_img('test/2.jpg', target_size=(32,32)) x = image.img_to_array(x) x = x.reshape((1,) + x.shape) x = x/255. 中做同样的事情再现了你的问题。

答案 2 :(得分:0)

执行以下操作....

arr.sort(function(a,b){return (!a || !b)? 0 : (a.key - b.key) })