Sort a list of Doubles with custom comparator for Double.NaN

我的梦境 提交于 2019-12-24 08:25:01

问题


I have the following list

scala>  List(Double.NaN, 0.0, 99.9, 34.2, 10.98, 7.0, 6.0, Double.NaN, 5.0, 2.0, 0.56, Double.NaN, 0.0, 10.0)
res0: List[Double] = List(NaN, 0.0, 99.9, 34.2, 10.98, 7.0, 6.0, NaN, 5.0, 2.0, 0.56, NaN, 0.0, 10.0)

This is my comparator function :

scala> def sortAscendingDouble(d1:Double, d2:Double) = {
     | if(d1.isNaN && !d2.isNaN)
     | d1 < d2
     | else if(!d1.isNaN && d2.isNaN)
     | d2 < d1
     | else d1< d2
     | }
sortAscendingDouble: (d1: Double, d2: Double)Boolean

I am trying to use it sortWith as follows :

scala> res0.sortWith((d1, d2)=> sortAscendingDouble(d1, d2))
res1: List[Double] = List(NaN, 0.0, 0.0, 0.56, 2.0, 5.0, 6.0, 7.0, 10.0, 10.98, 34.2, 99.9, NaN, NaN)

I do not understand why the first NaN does not go to end of the list.

My expected output for ascending order sorted list is :

List(0.0, 0.0, 0.56, 2.0, 5.0, 6.0, 7.0, 10.0, 10.98, 34.2, 99.9, NaN, NaN, NaN)

My expected output for descending order sorted list is :

List(99.9, 34.2, 10.98, 10.0, 7.0, 6.0, 5.0, 2.0, 0.56, 0.0, 0.0, NaN, NaN, NaN

In case of both Ascending order sort and descending order sort I want the NaNs to go at the end.

I know sortWith enables us to write own comparator. Can someone help me with this?


回答1:


The problem is that comparing a any number (including NaN itself) with Nan will always return false. Thus your third condition is wrong because d2 < d1 will be false but it must be true. You can fix it by using fixed return values for your functions on those especial cases.

/** Compares two doubles and returns true if the first value is equals or less than the second */
def sortAscendingDouble(d1: Double, d2: Double): Boolean =
  if (d1.isNaN && d2.isNaN)
    false // doesn't matter if true or false.
  else if(d1.isNaN && !d2.isNaN)
    false // NaN always goes after any non-NaN double.
  else if(!d1.isNaN && d2.isNaN)
    true // NaN always goes after any non-NaN double.
  else
    d1 < d2 // Standard double comparison. This should take care of any repetitive Doubles

/** Compares two doubles and returns true if the first value is equals or greater than the second */
def sortDescendingDouble(d1: Double, d2: Double): Boolean =
  if (d1.isNaN && d2.isNaN)
    false // doesn't matter if true or false.
  else if(d1.isNaN && !d2.isNaN)
    false // NaN always goes after any non-NaN double.
  else if(!d1.isNaN && d2.isNaN)
    true // NaN always goes after any non-NaN double.
  else
    d1 > d2 // Standard double comparison. This should take care of any repetitive Doubles

list.sortWith(sortAscendingDouble)
// List[Double] = List(0.0, 0.0, 0.56, 2.0, 5.0, 6.0, 7.0, 10.0, 10.98, 34.2, 99.9, NaN, NaN, NaN)

list.sortWith(sortDescendingDouble)
// List[Double] = List(99.9, 34.2, 10.98, 10.0, 7.0, 6.0, 5.0, 2.0, 0.56, 0.0, 0.0, NaN, NaN, NaN)


来源:https://stackoverflow.com/questions/53618257/sort-a-list-of-doubles-with-custom-comparator-for-double-nan

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!