Кажется, я постоянно сталкиваюсь с этой проблемой. Я хочу изменить некоторые элементы в списке, но при этом мне нужно сохранить какое-то состояние, поэтому карта не работает.
Вот пример:
scala> val l1 = List("a","b","c","d","e","f","b","c","e","b","a")
l1: List[String] = List(a, b, c, d, e, f, b, c, e, b, a)
Я хочу изменить имя всех дубликатов. так что я хочу закончить с этим:
List(a1, b1, c1, d, e1, f, b2, c2, e2, b3, a2)
Получить копии легко :
scala> val d = l1.diff(l1.distinct).distinct
d: List[String] = List(b, c, e, a)
Теперь я застрял. Я заставил это работать, преобразовав d в HashMap со счетчиком и написав функцию для итерации по l1 и обновления ее и хэша перед рекурсией. Это прекрасно работает, но выглядит довольно уродливо для меня.
Но я всегда думал, что должен быть способ сделать это с классами коллекций.
Вот остальная часть моего решения, которое мне не нравится:
val m = d.map( _ -> 1).toMap
def makeIt(ms: Map[String, Int], ol: Iterator[String], res: List[String]=List[String]()) :List[String] = {
if( !ol.hasNext) return res
val no = ol.next()
val (p,nm) = ms.get(no) match {
case Some(v) => (s"$no$v", ms.updated(no,v+1))
case None => (no,ms)
}
makeIt(nm,ol,res :+ p)
}
makeIt(m,l1.iterator)
Что дает мне то, что я хочу
res2: List[String] = List(a1, b1, c1, d, e1, f, b2, c2, e2, b3, a2)
Я чувствую, что мне нужен "mapWithState", где я могу просто что-то передать. Как фолд-иш. Может быть, он существует, просто я его еще не нашел?
Спасибо
-------ОБНОВЛЕНИЕ---------
Комментарий @Aluan Haddad указал мне на это направление. Что разрушает порядок, что нормально для моего случая. Но «состояние» несет zipWithIndex. Я ищу более общий случай, когда состояние потребует некоторых вычислений для каждого элемента. Но для этого простого случая мне это нравится:
l1.groupBy(x=>x).values.flatMap( v =>{
if( v.length <= 1 ) v else {
v.zipWithIndex.map{ case (s,i) => s"$s${i+1}"}
}
})
res7: Iterable[String] = List(e1, e2, f, a1, a2, b1, b2, b3, c1, c2, d)
Похоже, вы хотите
groupBy
@aluan Думаю, я мог бы использовать
groupBy
только для посещения элементов, которые нужно изменить (и пропуститьmatch
), но я не понимаю, как это помогает мне сохранять состояние при изменении имен?Я должен был сказать, что предлагал
groupBy
в качестве альтернативы отслеживанию состояния. Таким образом, вы можете написать что-то вродеvalues.groupBy(x => x).map((g => g.zipWithIndex.map(...
Я думаю, что это сработало бы для этого случая и было бы лучше, чем то, что у меня есть. Но на самом деле меня интересует более общий случай, когда мое «состояние» более сложное, чем увеличивающееся целое число.