Замена каждого вхождения некоторого элемента другим элементом - PullRequest
4 голосов
/ 13 ноября 2010

Какой лучший способ Scala заменить из какого-либо списка каждое вхождение элемента x каким-либо другим элементом y? Вот чем я сейчас занимаюсь:

list map { 
  case `x` => y
  case a => a
}

Есть ли более краткий доступный способ? Спасибо.

Ответы [ 3 ]

9 голосов
/ 13 ноября 2010
list.map(i => if (i==x) y else i)

как насчет этого?

7 голосов
/ 13 ноября 2010

Если вам нужно много делать, вы можете написать служебную функцию:

def replace[T](x: T, y: T) = (i: T) => if (i == x) y else i

Это позволит вам написать

list map replace(x, y)

Или для инфиксного синтаксиса:

class ReplaceWith[T](x: T) {
   def replaceWith(y: T) = (i: T) => if (i == x) y else i
}
object ReplaceWith {
   implicit def any2replaceWith[T](x: T) = new ReplaceWith(x)
}

// now you can write
list map (x replaceWith y)

Другое решение - использовать карту:

list map Map(x -> y).withDefault(identity)

С функцией полезности:

scala> def replace[T](pairs: (T, T)*) = Map(pairs: _*).withDefault(identity)
replace: [T](pairs: (T, T)*)scala.collection.immutable.Map[T,T]

scala> List(1,2,3) map replace(1 -> -1, 3 -> 4)
res0: List[Int] = List(-1, 2, 4)
2 голосов
/ 13 ноября 2010

Вы можете создать собственный метод для замены:

class RichIterable[E] (col: Iterable[E]) {
    def replace(pairs: (E, E)*): Iterable[E] = col map {
        a => pairs.find(_._1 == a) match {
            case None => a
            case Some(p) => p._2
        }
    }
}

object RichIterable {
    implicit def iterable2RichIterable[A](col: Iterable[A]) = 
        new RichIterable(col)
}

Замена элементов должна быть легкой:

scala> import RichIterable._
import RichIterable._
scala> List(1, 2, 3, 4, 5, 4, 3, 4, 7).replace(3 -> 30, 4 -> 40)
res1: Iterable[Int] = List(1, 2, 30, 40, 5, 40, 30, 40, 7)
...