【问题标题】:How to check if there intersection in list of pairs?如何检查对列表中是否有交集?
【发布时间】:2019-03-07 01:16:09
【问题描述】:

我们有一个配对列表,例如如下

val listPairs = List(("a", "a"), ("b", "a"), ("d", "d"), ("a", "c"))

我想查找是否存在i != j这样的

listPairs(i)._1 = listPairs(j)._2

并打印找到的第一个这样的i, j

所以对于listPairs,肯定有i = 0, j = 1

我自己能找到的唯一方法是简单地遍历每个索引i, j, i < j 的列表并进行比较。但这是一个带有可变变量的丑陋嵌套循环。

谁能提出更好的方法?

【问题讨论】:

    标签: scala collections


    【解决方案1】:

    对 Leo 的回答稍作修改,我使用zipWithIndex 来避免按索引访问列表。

    def checkIntersections[T](pairs: List[(T, T)]): List[(Int, Int)] = {
      val pairsWithIndex = pairs.zipWithIndex
    
      val result = for {
        ((a, _), i) <- pairsWithIndex
        ((_, b), j) <- pairsWithIndex
        if i != j && a == b
      } yield (i, j)
    
      result.toList
    }
    
    checkIntersections(List(("a", "a"), ("b", "a"), ("d", "d"), ("a", "c")))
    // res0: List[(Int, Int)] = List((0,1), (3,0), (3,1))
    

    【讨论】:

      【解决方案2】:

      您可以使用for-comprehensionguard,如下所示:

      val listPairs = List(("a", "a"), ("b", "a"), ("d", "d"), ("a", "c"))
      
      val sz = listPairs.size
      
      for {
        i <- (0 until sz)
        j <- (0 until sz)
        if i != j && listPairs(i)._1 == listPairs(j)._2
      } yield (i, j)
      // res1: scala.collection.immutable.IndexedSeq[(Int, Int)] = Vector((0,1), (3,0), (3,1))
      

      如果只需要与 i

      for {
        i <- (0 until sz)
        j <- (i+1 until sz)
        if listPairs(i)._1 == listPairs(j)._2
      } yield (i, j)
      // res2: scala.collection.immutable.IndexedSeq[(Int, Int)] = Vector((0,1))
      

      【讨论】:

      • 这确实有效,但您使用的方法非常效率低下:列表中的sizeO(N)apply按索引列出的列表是 O(I)
      • 你说得对,路易斯。如果性能是重中之重,我可能会建议不要使用List,而是使用Array 来实现更高效的索引和迭代。
      【解决方案3】:

      使用尾递归

      val listPairs = List(("a", "a"), ("b", "c"), ("d", "d"), ("y", "a"))
      def res(lst: List[(String,String)], count: Int): Option[(Int,Int)] = {
      if (lst.isEmpty) return None
      lst.tail.indexWhere(_._2 == lst.head._1) match {
        case -1 => res(lst.tail, count+1)
        case a: Int => Some((count,count+a+1))
      }
      }
      println(res(listPairs, 0))
      

      输出:一些((0,3))

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-11-06
        • 2017-07-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多