0

鉴于以下列表:

val l = List("A", "A", "C", "C", "B", "C")

如何为每个元素添加自动递增后缀,以便最终得到一个不再包含重复项的列表,如下所示(排序无关紧要):

List("A0", "A1", "C0", "C1", "C2", "B0")
4

3 回答 3

3

写完这个问题后我自己发现了

val l = List("A", "A", "C", "C", "B", "C")
l.groupBy(identity) // Map(A->List(A,A),C->List(C,C,C),B->List(B))
  .values.flatMap(_.zipWithIndex) // List((A,0),(A,1),(C,0),(C,1),(C,2),(B,0))
  .map{ case (str, i) => s"$str$i"}

如果有更好的解决方案(使用foldLeft可能)请告诉我

于 2017-06-07T12:07:34.597 回答
1

以一种简单的方式:

def transformList(list : List[String]) : List[String] = {
  val buf: mutable.Map[String, Int] = mutable.Map.empty
  list.map {
    x => {
      val i = buf.getOrElseUpdate(x, 0)
      val result = s"${x.toString}$i"
      buf.put(x, i + 1)
      result
    }
  }
}

transformList( List("A", "A", "C", "C", "B", "C"))
于 2017-06-07T13:41:52.050 回答
0

也许不是最易读的解决方案,但是......

def appendCount(l: List[String]): List[String] = {
  // Since we're doing zero-based counting, we need to use `getOrElse(e, -1) + 1`
  // to indicate a first-time element count as 0. 
  val counts = 
    l.foldLeft(Map[String, Int]())((acc, e) => 
      acc + (e -> (acc.getOrElse(e, -1) + 1))
    )

  val (appendedList, _) = 
    l.foldRight(List[String](), counts){ case (e, (li, m)) =>
      // Prepend the element with its count to the accumulated list.
      // Decrement that element's count within the map of element counts
      (s"$e${m(e)}" :: li, m + (e -> (m(e) - 1)))
    }
  appendedList
}

这里的想法是创建列表中每个元素的计数。然后,您从原始值列表的后面进行迭代,并将计数附加到该值,同时递减计数映射。

您需要在此处定义一个助手,因为foldRight将需要 newList[String]和 counts 作为累加器(因此,将返回两者)。你只会忽略最后的计数(无论如何它们都会-1)。

我会说你的方式可能更清楚。如果这是一个问题,您需要进行基准测试以查看哪个更快。

爱迪生

于 2017-06-07T13:20:17.807 回答