返回类型的不同元素((String,String),Double)

时间:2014-07-01 13:30:50

标签: scala

val v : Array[((String, String), Double)] = Array( ( ("a" , "b") , 1.0) , (("b" , "a") , 1.0) )
                                                  //> v  : Array[((String, String), Double)] = Array(((a,b),1.0), ((b,a),1.0))

  val d = v.distinct                              //> d  : Array[((String, String), Double)] = Array(((a,b),1.0), ((b,a),1.0))

一个独特的函数应该输出( ("a" , "b") , 1.0),因为(("b" , "a") , 1.0)在数组

使用:

  Array( ( ("a" , "b") , 1.0) , (("a" , "b") , 1.0) ).distinct

返回不同的元素:Array(((a,b),1.0))

可以修改distinct函数以返回不同的Tuple元素而不管它们的顺序如何,或者我是否需要交换元组的位置以使每个元素看起来有序?

3 个答案:

答案 0 :(得分:1)

确实元组t1:(A,B)不等于t2:(B,A)因为顺序很重要(t1._1 != t2._1)。如果您想要一个不保留顺序的数据结构,因此在与另一个实例进行比较时不使用它,那么请使用类似Set的内容。只是为了说明这一点:

scala> (1, 2) == (2, 1)
res0: Boolean = false

scala> Set(1, 2) == Set(2, 1)
res1: Boolean = true

如果您仍想使用元组,那么您可以编写自己的distinct实现。遗憾的是,distinct不是更高阶函数,可以使用def sorted[B >: A](implicit ord: math.Ordering[B]): List[A]之类的比较策略。

答案 1 :(得分:1)

基于LimbSoup的评论:

如果您愿意使用另一个案例类代替Tuple2,您可以使用equals(Any)覆盖轻松创建自己的无序元组实现:

case class UT2[+T1, +T2](_1: T1, _2: T2)  {
  override def hashCode(): Int = _1.hashCode() ^ _2.hashCode()

  override def equals(that: Any): Boolean ={
   that match {
    case UT2(o1, o2) => (_1 == o1 && _2 == o2) || (_1 == o2 && _2 == o1)
    case _ => false
  }}

  lazy val tuple: (T1, T2) = (_1, _2)
}

请注意,您必须覆盖hashCode(),否则它将不适用于似乎在内部使用哈希集just because you shoulddistinct

val seq = Array((UT2("a", "b") , 1.0), (UT2("b", "a"), 1.0))
seq.distinct.toList // List((UT2(a,b),1.0))

如果您想要在大多数地方的普通元组和无序元组之间进行自动转换,您可以提供隐式转换:

object UnorderedTupleImplicits {
  implicit def Tuple2UnorderedTuple[T1, T2](t: (T1, T2)): UT2[T1, T2] = UT2(t._1, t._2)
  implicit def UnorderedTuple2Tuple[T1, T2](ut: UT2[T1, T2]): (T1, T2) = ut.tuple
}
import UnorderedTupleImplicits._
val ut: (UT2[String, String], Double) = (("a", "b"), 1.0)

答案 2 :(得分:0)

使用Aleksey Izmailov回答为基础:

    val v : Array[((String, String), Double)] = Array( ( ("a" , "b") , 1.0) , (("b" , "a") , 1.0) )    
      v.map(m => (Set(m._1._1 , m._1._2) , m._2) ).distinct
 res0: Array[(scala.collection.immutable.Set[String], Double)] = Array((Set(a, b),1.0))