Scala 将自动递增后缀附加到列表的重复元素

Scala 将自动递增后缀附加到列表的重复元素,scala,list,suffix,Scala,List,Suffix,鉴于以下清单: val l = List("A", "A", "C", "C", "B", "C") 如何为每个元素添加一个自动递增的后缀,从而得到一个不再包含重复项的列表,如下所示(顺序无关紧要): 写了这个问题后,我自己发现了 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.flat

鉴于以下清单:

val l = List("A", "A", "C", "C", "B", "C")
如何为每个元素添加一个自动递增的后缀,从而得到一个不再包含重复项的列表,如下所示(顺序无关紧要):


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

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
也许),请让我知道

我是在写了这个问题后自己发现的

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
也许),请让我知道也许不是最可读的解决方案,但是

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
将需要新的
List[String]
和计数作为累加器(因此,将返回两者)。您只需忽略末尾的计数(无论如何,它们都是
-1

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


.

也许不是最具可读性的解决方案,但

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
将需要新的
List[String]
和计数作为累加器(因此,将返回两者)。您只需忽略末尾的计数(无论如何,它们都是
-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"))

以一种简单的方式:

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"))


这些元素将被排序,对吗?不一定,我已经编辑了我的问题和答案来反映这一点,好的,所以你现在假设类似的元素将被分组,是吗?不,我在列表中完全没有假设你试图实现什么算法?它是某种BWT吗?还是什么?这些元素会被排序,对吗?不一定,我已经编辑了我的问题和答案来反映这一点,好的,所以你现在假设类似的元素会被分组,是吗?不,我绝对不会在列表上做任何假设。你想实现什么算法?它是某种BWT吗?还是什么?这里需要注意的重要一点是,您会因为
groupBy
而失去订单。再说一遍,我不在乎订单。最后我可以简单地
sortBy
,这不是一个大交易,我认为这可能是最好的,不引入可变状态。我在考虑一个计数图,尝试一个<代码> FordRebug 并在遇到元素时减少计数,但这并不太好。我也开始了 FordDouth。但是在中间丢失了。很好地完成了。
mapValues()
flattle
步骤可以组合在一个
flatMap()
中,如下所示:
groupBy(identity.values.flatMap({uu.zipWithIndex.map{case(s,i)=>s“$s$i”})
这里需要注意的一点是,您将因为
groupBy
而失去订单。同样,我不关心订单。最后我可以简单地
sortBy
,这不是一个大交易,我认为这可能是最好的,不引入可变状态。我在考虑一个计数图,尝试一个<代码> FordRebug 并在遇到元素时减少计数,但这并不太好。我也开始了 FordDouth。但是在中间丢失了。很好地完成了。
mapValues()
plant
步骤可以组合在一个
flatMap()
中,如下所示:
groupBy(identity).values.flatMap({uu.zipWithIndex.map{case(s,i)=>s“$s$i”})
我认为使用
groupBy(identity).mapValues({uu.length)与使用Map访问和处理
getOrElse
的复杂性相比,
foldRight
中的
getOrElse
调用是不必要的。编辑。我认为你的更可读,但我的更快。我认为使用
groupBy(identity)。与使用Map访问和处理
getOrElse
的复杂性相比,使用
foldRight
中的
getOrElse
调用是不必要的。编辑。我认为你的更具可读性,但我的更快。好吧,这实际上是一个品味和上下文的问题,在这一点上,可变或不变的映射在这里都是可用的。我同意它在功能上是相同的。但是你应该创建一个函数,这样你就不会暴露易变性。我想为什么不更新呢?嗯,这实际上是一个品味和上下文的问题。在这里,易变映射和不可变映射都是可用的。我同意它在功能上是相同的。但是你应该做一个函数,这样你就不会暴露易变性。我想为什么不更新呢