给定RDD[(A, B)]
,A
和B
之间存在多对多关系,如何对关系的交叉点进行分组?
即。如果可以通过一个或多个A
从一个A
到另一个B
建立关系,则应将它们分组。同样,B
可以通过A
s进行分组。
例如,集合:
(1, 'a')
(2, 'a')
(2, 'b')
(1, 'c')
(3, 'f')
(4, 'f')
(5, 'g')
应该分组到
([1,2], ['a','b','c'])
([3,4], ['f'])
([5], ['g'])
我可以使用groupByKey
获取
(1, ['a', 'c'])
(2, ['a', 'b'])
(3, ['f'])
(4, ['f'])
(5, ['g'])
以及
('a', [1, 2])
('b', [2])
('c', [1])
('f', [3,4])
('g', [5])
但是我不知道从哪里拿它。
答案 0 :(得分:0)
object ManyToMany extends App {
val m = List((1, 'a'),
(2, 'a'),
(2, 'b'),
(1, 'c'),
(3, 'f'),
(4, 'f'),
(5, 'g'))
val mInt: Map[Int, Set[Char]] = m.groupBy(_._1).map { case (a, b) => a -> b.map { case (c, d) => d }.toSet }
val mChar: Map[Char, Set[Int]] = m.groupBy(_._2).map { case (a, b) => a -> b.map { case (c, d) => c }.toSet }
def isIntersect[A](as: List[Set[A]], bs: Set[A]): List[Set[A]] = as.filter { x => x.exists { y => bs.contains(y) } }
val c = m.map { case (a, b) => mInt(a) }.foldLeft(List.empty[Set[Char]]) {
case (sum, item) =>
isIntersect(sum, item) match {
case Nil => item :: sum
case List(x) =>
sum.filterNot(_ == x) ++ List(x ++ item)
}
}
val d = c.map(x => (x, x.map(mChar(_)).foldLeft(Set.empty[Int]) { case (sum, i) => sum ++ i }))
println(d)
}
result:
List((Set(g),Set(5)), (Set(a, c, b),Set(1, 2)), (Set(f),Set(3, 4)))