在scala中应用多个字符串转换

时间:2012-07-05 17:30:53

标签: scala functional-programming scalaz

我想在scala中以函数方式对字符串执行几个有序和连续的replaceAll(...,...)。

最优雅的解决方案是什么? Scalaz欢迎! ;)

5 个答案:

答案 0 :(得分:15)

如果它只是几个调用,那么只是链接它们。否则我想我会试试这个:

Seq("a" -> "b", "b" -> "a").foldLeft("abab"){case (z, (s,r)) => z.replaceAll(s, r)}

或者,如果您喜欢使用令人困惑的通配符和额外闭包的较短代码:

Seq("a" -> "b", "b" -> "a").foldLeft("abab"){_.replaceAll _ tupled(_)}

答案 1 :(得分:13)

首先,让我们从replaceAll方法中获取一个函数:

scala> val replace = (from: String, to: String) => (_:String).replaceAll(from, to)
replace: (String, String) => String => java.lang.String = <function2>

现在,您可以在scalaz中使用Functor实例作为函数defined。这样你就可以使用map来构建函数(或者使用unicode别名使其看起来更好)。

看起来像这样:

scala> replace("from", "to") ∘ replace("to", "from") ∘ replace("some", "none")
res0: String => java.lang.String = <function1>

如果您更喜欢haskell-way compose(从右到左),请使用contramap

scala> replace("some", "none") ∙ replace("to", "from") ∙ replace ("from", "to")
res2: String => java.lang.String = <function1>

您还可以通过Category instance获得一些乐趣:

scala> replace("from", "to") ⋙ replace("to", "from") ⋙ replace("some", "none")
res5: String => java.lang.String = <function1>

scala> replace("some", "none") ⋘ replace("to", "from") ⋘ replace ("from", "to")
res7: String => java.lang.String = <function1>

并应用它:

scala> "somestringfromto" |> res0
res3: java.lang.String = nonestringfromfrom

scala> res2("somestringfromto")
res4: java.lang.String = nonestringfromfrom

scala> "somestringfromto" |> res5
res6: java.lang.String = nonestringfromfrom

scala> res7("somestringfromto")
res8: java.lang.String = nonestringfromfrom

答案 2 :(得分:4)

另一个基于Scalaz的解决方案是使用Endo幺半群。这个monoid捕获身份函数(作为monoid的标识元素)和函数组合(作为monoid的追加操作)。如果您要应用任意大小(甚至可能为空)的函数列表,此解决方案将特别有用。

val replace = (from: String, to: String) => (_:String).replaceAll(from, to)

val f: Endo[String] = List(
  replace("some", "none"),
  replace("to", "from"),
  replace("from", "to")    
).foldMap(_.endo)

e.g。 (使用folone的一个例子)

scala> f.run("somestringfromto")
res0: String = nonestringfromfrom

答案 3 :(得分:3)

使用匿名参数定义替换函数,然后您可以将连续替换函数链接在一起。

scala> val s = "hello world"
res0: java.lang.String = hello world

scala> def replace = s.replaceAll(_, _)
replace: (java.lang.String, java.lang.String) => java.lang.String

scala> replace("h", "H")  replace("w", "W")
res1: java.lang.String = Hello World

答案 4 :(得分:-1)

#to replace or remove multiple substrings in scala in dataframe's string column

import play.api.libs.json._
#to find
def isContainingContent(str:String,regexStr:String):Boolean={
  val regex=new scala.util.matching.Regex(regexStr)
  val containingRemovables= regex.findFirstIn(str)
  containingRemovables match{
    case Some(s) => true
    case None => false
  }
}
val colContentPresent= udf((str: String,regex:String) => {
  isContainingContent(str,regex)
})
#to remove
val cleanPayloadOfRemovableContent= udf((str: String,regexStr:String) => {
  val regex=new scala.util.matching.Regex(regexStr)
  val cleanedStr= regex.replaceAllIn(str,"")
  cleanedStr
})
#to define
val removableContentRegex=
"<log:Logs>[\\s\\S]*?</log:Logs>|\\\\n<![\\s\\S]*?-->|<\\?xml[\\s\\S]*?\\?>"

#to call
val dfPayloadLogPresent = dfXMLCheck.withColumn("logsPresentInit", colContentPresent($"payload",lit(removableContentRegex)))
val dfCleanedXML = dfPayloadLogPresent.withColumn("payload", cleanPayloadOfRemovableContent($"payload",lit(removableContentRegex)))