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元素而不管它们的顺序如何,或者我是否需要交换元组的位置以使每个元素看起来有序?
答案 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 should的distinct
。
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))