Scala:在一组字符串上执行多个映射和平面映射



我对 scala(以及一般的编程(很陌生,但已经想出了一个不太完美的解决方案来解决我遇到的问题 - 我想知道是否有人有一个更优雅/更高效的解决方案?

我有一组(非常大的(字符串,下面是一个小示例,用于复制目的:

val brands = Set("Brand one", "BRAND-two!!!", "brand_Three1, brandThree2", "brand04")

现在我想做的是清理这个集合,以便我有一个新的干净集合,其中:

  1. 用逗号分隔的任何字符串都将拆分为单独的字符串
  2. 前导空格和非字母数字(和 _ -(字符是 删除
  3. 任何带有空格的字符串都将替换为三个版本的 该字符串(一个没有空格,一个带有"-"而不是空格,一个和一个带有"_"(

到目前为止,我拥有的代码是这样做的,但它分两步完成,因此迭代列表两次(效率低下(:

val brands_clean = brands.flatMap(
_.toLowerCase.split(",").map(
_.trim.replaceAll("[^A-Za-z0-9\-\_\s]+", "")
)
)
def spaceVariations(v: String) = if (v.contains(" ")) Set(v.replaceAll(" ", "-"), v.replaceAll(" ", "_"), v.replaceAll(" ", "")) else Set(v)
val brands_final = brands_clean.flatMap(spaceVariations(_))

我尝试通过将 placeAll a map 或 flatMap 附加到 replaceAll a map 或 flatMap 将 spaceVariations 函数直接合并到主代码中:

// using the function call
.flatMap(spaceVariations(_))   
// or using a function directly within the code
.flatMap {v => if (v.contains(" ")) Set(v.replaceAll(" ", "-"), v.replaceAll(" ", "_"), v.replaceAll(" ", "")) else Set(v) }

但我收到以下错误:

error: type mismatch;
found   : Array[Nothing]
required: scala.collection.GenTraversableOnce[?]

我不确定我是否理解为什么这在这里不起作用,或者是否有更好的方法来实现我想要实现的目标?

brands.flatMap(
_.toLowerCase.split(",").map(
_.trim.replaceAll("""[^w-]""", "")
)
).flatMap(spaceVariations)

对我有用,不确定您在哪里(或为什么(收到错误(我稍微清理了您的正则表达式以使其更简洁,但这无关紧要(。

请注意,这仍然遍历该集两次。集合在 scala 中并不懒惰,因此,它将首先用中间集合完成第一个flatMap,然后从下一个集合开始。

如果要保存扫描,则应从Iterator而不是集合开始,因为迭代器是惰性的,并且会在继续下一个元素之前将每个元素发送到整个链中:

brands
.iterator
.flatMap { _.toLowerCase.split(",") }
.map(_.trim)
.map { _.replaceAll("""[^w-]""", "") }
.flatMap(spaceVariations)
.toSet

基于您的Set将始终如下所示的假设:

def spaceVariations(v: String) = if (v.contains(" ")) Set(v.replaceAll(" ", "-"), v.replaceAll(" ", "_"), v.replaceAll(" ", "")) else Set(v)
val brands = Set("Brand one", "BRAND-two!!!", "brand_Three1, brandThree2", "brand04")
brands.map( x => if (x.contains(",") ) x.split(",") else x ).flatMap {
case str: String => Array(str)
case a : Array[String] => a 
}.map(_.trim.toLowerCase.replaceAll("[^A-Za-z0-9\-\_\s]+", "")).map(spaceVariations(_))

给出输出:

Set(Set(brand-one, brand_one, brandone), Set(brandthree2), Set(brand04), Set(brand-two), Set(brand_three1))

最新更新