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

时间:2017-08-03 14:28:34

标签: scala

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

我有一个(非常大的)字符串集,下面的一个小例子用于复制目的:

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

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

  1. 用逗号分隔的任何字符串都会拆分为单独的字符串
  2. 前导空格和非字母数字(和_ - )字符 删除
  3. 任何带空格的字符串都被三个版本的 那个字符串(一个没有空格,一个带有“ - ”而不是空格,一个带有“_”)
  4. 到目前为止,我所做的代码都是这样做的,但它分两步完成,因此在列表上迭代两次(效率很低):

       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(_))
    

    我尝试将spaceVariations函数直接合并到主代码中,方法是将replaceAll附加到map或flatMap:

    // 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[?]
    

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

2 个答案:

答案 0 :(得分:3)

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

为我工作,不知道你在哪里(或为什么)得到错误(我清理了你的正则表达式,使它更简洁,但这不重要)。

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

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

Iterator

答案 1 :(得分:1)

基于您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))