首页 > 解决方案 > 匹配元组中第一个引用项的第 n 个条目

问题描述

我有一个List包含元组的元组(e:Int, a:String, b:String),其中e指向将增加的 eventid,a表示元组中第一个引用的项目并b表示第二个。

该列表按 eventid 排序,我需要获取匹配 n 的项目的第 n 个条目。

val ad = List(( 10 ,"W","A"),( 20 ,"W","E"),( 30 ,"I","W"),( 40 ,"A","E"),( 50 ,"P","E"),
( 60 ,"S","A"),( 70 ,"A","P"),( 80 ,"A","I"),( 100 ,"A","S"),( 110 ,"I","S"),
( 120 ,"A","N"),( 130 ,"E","N"))

预期的结果是

(1,W)
(1,I)
(1,P)
(1,S)
(2,A)
(4,E)

Wa第一次出现在 eventid=10 并且应该被捕获。对于 I、P 和 S。A 出现在 eventid=20 中,b但在 eventid=40 中再次引用,所以它应该被捕获为(2,A)。对于 E 也是如此。

我正在尝试使用以下代码,foldLeft但出现错误和不正确的结果。

val t = ( 1 until ad.size).map {
  p => {
    ad.foldLeft((List.empty[(Int, String)], Map[String, Int]().empty, Map[String, Int]().empty)) {
      case ((a, b, c), x) => {

        (a, x+ ( b, (b.getOrElse(x._2, 0) + 1),  x + (x._3 , (b.getOrElse(x._3, 0) + 1))
      }
    }._1
  }
}

错误:

Error:(9, 8) ')' expected but '}' found.
      }
      ^

我在foldLeft这里的操作很困难,可以解决吗?

标签: scala

解决方案


这应该有效。

final case class Entry(eventId: Int, a: String, b: String)

def getNthEntry(data: List[Entry]): Map[String, Int] = {
  def getPlusOne(map: Map[String, Int], key: String): (String, Int) =
    key -> (map.getOrElse(key, default = 0) + 1)

  @annotation.tailrec
  def loop(remeaining: List[Entry], acc: Map[String, Int], bCount: Map[String, Int]): Map[String, Int] =
    remeaining match {
      case Nil =>
        acc

      case Entry(_, a, b) :: xs =>
        val newAcc = 
          if (acc.contains(a))
            acc
          else
            acc + getPlusOne(map = bCount, key = a)

        val newBCount =
          bCount + getPlusOne(map = bCount, key = b)

        loop(remeaining = xs, newAcc, newBCount)
    }

  loop(remeaining = data, acc = Map.empty, bCount = Map.empty)
}

注意:从技术上讲,您可以对foldLeft. 但是,恕我直言,手工制作的尾递归算法更容易阅读


推荐阅读