【问题标题】:scala - string parsing without Regexscala - 没有正则表达式的字符串解析
【发布时间】:2019-01-08 09:37:50
【问题描述】:

我有各种类型的字符串,如下所示:

sales_data_type
saledatatypes
sales_data.new.metric1
sales_data.type.other.metric2
sales_data.type3.metric3

我正在尝试解析它们以获取在最后一个点之前和之后带有单词的子字符串。例如:new.metric1other.metric2type3.metric3。如果单词不包含点,则必须按原样返回:sales_data_type, saledatatypes。 使用正则表达式可以这样做:

val infoStr = "sales_data.type.other.metric2"
val pattern = ".*?([^.]+\\.)?([^.]+)$"  
println(infoStr.replaceAll(pattern, "$1$2"))
// prints other.metric2
// for saledatatypes just prints nullsaledatatypes ??? but seems to work 

我想找到一种方法来使用 Scala 实现这一点,而不使用 Regex 来扩展我对 Scala 特性的理解。将不胜感激任何想法。

【问题讨论】:

    标签: string scala pattern-matching


    【解决方案1】:

    单线:

    dataStr.split('.').takeRight(2).mkString(".")
    

    takeRight(2) 如果有 2 个要占用,则将占用最后一个 2,否则它将占用最后一个,并且仅占用 1 个。mkString(".") 将仅在点有 2 个元素时重新插入点之间,否则它将保持字符串不变。

    【讨论】:

      【解决方案2】:

      这里有很多 scala 功能供您使用。

      val string = "head.middle.last"
      
      val split = string.split('.') // Array(head, middle, last)
      
      val result = split.toSeq match {
        case Seq(word) ⇒ word
        case _ :+ before :+ after ⇒ s"$before.$after"
      }
      
      println(result) // middle.last
      

      首先,我们拆分您的 . 上的字符串并获取各个部分。
      然后我们对这些部分进行模式匹配,首先检查是否只有一个(在这种情况下我们只返回它),然后获取 seq 中的最后两个元素。
      最后,我们使用字符串插值将. 放回最后两个之间。

      【讨论】:

        【解决方案3】:

        一种方法:

        val value = "sales_data.type.other.metric2"
        val elems = value.split("\\.").toList
        
        elems match {
          case _:+beforeLast:+last => s"${beforeLast}.${last}"
          case _ => throw new NoSuchElementException
        }
        

        【讨论】:

          【解决方案4】:
          for(s<-strs) yield {val s1 = s.split('.');
               if(s1.size>=2)s1.takeRight(2).mkString(".") else s }
          

          for(s<-strs) yield { val s1 = s.split('.');
              if(s1.size>=2)s1.init.last+'.'+s1.last else s }
          

          在 Scala REPL 中:

          scala> val strs =
          Vector("sales_data_type","saledatatypes","sales_data.new.metric1","sales_data.type.other.metric2","sales_d
          ata.type3.metric3")
          strs: scala.collection.immutable.Vector[String] = Vector(sales_data_type, saledatatypes, sales_data.new.metric1, sales_data.
          type.other.metric2, sales_data.type3.metric3)
          
          
          scala> for(s<-strs) yield { val s1 = s.split('.');if(s1.size>=2)s1.takeRight(2).mkString(".") else s }
          res62: scala.collection.immutable.Vector[String] = Vector(sales_data_type, saledatatypes, new.metric1, other.metric2, type3.
          metric3)
          
          scala> for(s<-strs) yield { val s1 = s.split('.');if(s1.size>=2)s1.init.last+'.'+s1.last else s }
          res60: scala.collection.immutable.Vector[String] = Vector(sales_data_type, saledatatypes, new.metric1, other.metric2, type3.
          metric3)
          

          【讨论】:

            【解决方案5】:

            使用scala match 并这样做

            def getFormattedStr(str:String):String={
              str.contains(".") match{
                case true=>{
                  val arr=str.split("\\.")
                  val len=arr.length
                  len match{
                    case 1=>str
                    case _=>arr(len-2)+"."+arr(len-1)
                  }
                }
                case _=>str
              }
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2020-08-25
              • 2022-01-25
              • 2016-04-29
              • 2012-08-07
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多