Returning distinct elements of type ((String,String) , Double)
1 2 3 4
| 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) 在数组中
使用 :
1
| Array( ( ("a" ,"b") , 1.0) , (("a" ,"b") , 1.0) ).distinct |
返回不同的元素:Array(((a,b),1.0))
是否可以修改 distinct 函数以返回不同的 Tuple 元素而不管它们的顺序如何,或者我是否需要交换元组的位置以使每个元素看起来都是有序的?
- 听起来您想为 Tuple2 重新定义 equals 的行为,而不是为集合重新定义 distinct 的行为。
-
Scala 的可能重复项:删除对象列表中的重复项
基于 LimbSoup\\ 的评论:
如果您愿意使用另一个 case 类代替 Tuple2,您可以使用 equals(Any) 覆盖轻松创建自己的无序元组实现:
1 2 3 4 5 6 7 8 9 10 11
| 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(),否则它将无法与 distinct 一起使用,而 distinct 似乎在内部使用了散列集,只是因为您应该这样做。
1 2
| val seq = Array ((UT2 ("a", "b") , 1.0), (UT2 ("b", "a"), 1.0))
seq. distinct. toList // List((UT2(a,b),1.0)) |
如果你想在大多数地方在普通元组和无序元组之间自动转换,你可以提供隐式转换:
1 2 3 4 5 6
| 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) |
确实元组t1:(A,B)不等于t2:(B,A),因为顺序很重要(t1._1 != t2._1)。如果你想要一个不保留顺序的数据结构,因此在与另一个实例进行比较时不使用它,那么使用类似 Set 的东西。只是为了说明这一点:
1 2 3 4 5
| 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].
这样的比较策略
使用 Aleksey Izmailov 回答作为基础:
1 2 3
| 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)) |
- 如果你有一个由两个相同字符串组成的元组,你想发生什么?喜欢 (("a","a"), 1.0)?