在Scala 2.8中,我需要调用List.min并提供我自己的比较函数来获取基于Tuple2的第二个元素的值.我不得不写这种代码:
val list = ("a", 5) :: ("b", 3) :: ("c", 2) :: Nil
list.min( new Ordering[Tuple2[String,Int]] {
def compare(x:Tuple2[String,Int],y:Tuple2[String,Int]): Int = x._2 compare y._2
} )
Run Code Online (Sandbox Code Playgroud)
有没有办法让这个更具可读性,或者像你可以用匿名函数创建一个Ordering list.sortBy(_._2)
?
psp*_*psp 29
来吧,伙计们,你让那个可怜的提问者"自己"找到了.相当破旧的表现.你可以再刮一下这样写:
list min Ordering[Int].on[(_,Int)](_._2)
Run Code Online (Sandbox Code Playgroud)
哪个仍然太吵了,但这就是我们现在所处的位置.
Fab*_*eeg 10
您可以做的一件事是使用更简洁的标准元组类型语法而不是使用Tuple2
:
val min = list.min(new Ordering[(String, Int)] {
def compare(x: (String, Int), y: (String, Int)): Int = x._2 compare y._2
})
Run Code Online (Sandbox Code Playgroud)
或者使用reduceLeft
一个更简洁的解决方案:
val min = list.reduceLeft((a, b) => (if (a._2 < b._2) a else b))
Run Code Online (Sandbox Code Playgroud)
或者您可以按标准对列表进行排序并获取first
元素(或last
最大值):
val min = list.sort( (a, b) => a._2 < b._2 ).first
Run Code Online (Sandbox Code Playgroud)
可以使用占位符语法进一步缩短:
val min = list.sort( _._2 < _._2 ).first
Run Code Online (Sandbox Code Playgroud)
正如您自己写的那样,可以缩短为:
val min = list.sortBy( _._2 ).first
Run Code Online (Sandbox Code Playgroud)
但正如你sortBy
自己建议的那样,我不确定你是否在寻找不同的东西.
该功能Ordering#on
见证了Ordering
一个反变异函子的事实.其他的还包括Comparator
,Function1
,Comparable
和scalaz.Equal
.
Scalaz提供了关于这些类型的统一视图,因此对于它们中的任何一个,您都可以value contramap f
使用符号表示来调整输入,value ? f
scala> import scalaz._
import scalaz._
scala> import Scalaz._
import Scalaz._
scala> val ordering = implicitly[scala.Ordering[Int]] ? {x: (_, Int) => x._2}
ordering: scala.math.Ordering[Tuple2[_, Int]] = scala.math.Ordering$$anon$2@34df289d
scala> List(("1", 1), ("2", 2)) min ordering
res2: (java.lang.String, Int) = (1,1)
Run Code Online (Sandbox Code Playgroud)
下面是从转换Ordering[Int]
到Ordering[(_, Int)]
的详细信息:
scala> scalaz.Scalaz.maContravariantImplicit[Ordering, Int](Ordering.Int).contramap { x: (_, Int) => x._2 }
res8: scala.math.Ordering[Tuple2[_, Int]] = scala.math.Ordering$$anon$2@4fa666bf
Run Code Online (Sandbox Code Playgroud)
list.min(Ordering.fromLessThan[(String, Int)](_._2 < _._2))
Run Code Online (Sandbox Code Playgroud)
当然,这仍然过于冗长.我可能会把它宣布为val
或object
.