从两两好友关系的记录中,找出三人中任意两人互为好友(三角好友)的Scala实现

曾经遇到一个问题: 

       有一个文件,其中每一行都记录了存在好友关系的两个人的userId。现要分析此文件,从两两朋友关系的记录中,找出所有的:三人中任意两人互为好友,即三角好友的存在,并打印出来

      

      当时现场没有写出来。最近尝试编写了下,抛去读取文件等基础工作,先实现了三角好友关系查找的实现,编写代码如下:

/**
  * Created by leisu on 2018/7/19.
  */
object TriangleFriendsRelationShip {

  def main(args: Array[String]) {

    //初始化一批数据
    val A = "A"
    val B = "B"
    val C = "C"
    val D = "D"
    val E = "E"
    val F = "F"
    val origin = List(A, B) :: List(A, C) :: List(A, D) :: List(B, C) :: List(B, D) :: List(C, D) :: List(C, E) :: List(C, F) :: List(E, F) :: Nil
    val oriSet: List[Set[String]] = origin.map(_.toSet)

    //调用方法处理
    val matchTupelList: List[Tuple2[Set[String], Set[String]]] = findCommonPoint(oriSet)
    val resultFinal = findMatchTriangle(oriSet, matchTupelList)

    //打印
    resultFinal.map(println)
  }

  /**
    * 找出List记录内,任两组数据中有共同顶点的匹配关系,组成新的Tuple  类似Set(A,B)+ Set(A,C) => Tuple2(Set(B,C),Set(A)) 这种结构
    * 并最终拼装成新list返回
    **/
  def findCommonPoint(list: List[Set[String]]): List[Tuple2[Set[String], Set[String]]] = list match {
    case headSet :: tail => {
      if (tail == Nil) Nil
      else {
        val lMatch = for (
          entrySet <- tail;
          item = ((headSet | entrySet) -- (headSet & entrySet), (headSet & entrySet)) //找出合并差
          if item._1.size == 2 //只有合并差为2时(即有共同定点时),才筛选出来
        ) yield item
        lMatch ::: findCommonPoint(tail) //递归,此次处理结果与前面处理结果进行合并
      }
    }
  }

  /**
    * 根据第三条边,找出完整的三角匹配关系
    */
  def findMatchTriangle(oriList: List[Set[String]], matchTupelList: List[Tuple2[Set[String], Set[String]]]): List[Set[String]] = {

    val resultList = for (entrySet <- oriList;
                          matchTuple <- matchTupelList;
                          result = entrySet | matchTuple._2
                          if (entrySet == matchTuple._1)
    ) yield result
    resultList.distinct //去重
  }
}


代码中案例的执行i结果如下:

Set(A, B, C)
Set(A, B, D)
Set(A, C, D)
Set(B, C, D)
Set(C, E, F)

Process finished with exit code 0

根据测试,此结果正确,完成功能

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

郭Albert

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值