【问题标题】:How to create case class from List[String]?如何从 List[String] 创建案例类?
【发布时间】:2015-10-07 21:19:20
【问题描述】:

这是我的代码

scala> s
res6: String = 2005-05-06 14:58:56 192 45.14.5.238 200 TCP_NC_MISS 1123 496 GET http c4.maxserving.com /gen.js ?site=5835&area=side_ros&group=sidebar&PageID=33364329499 - DIRECT c4.maxserving.com application/x-javascript "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)" PROXIED Web%20Advertisements - 192.16.170.44 SG-HTTP-Service - none -

scala> s.split("\\s")
res7: Array[String] = Array(2005-05-06, 14:58:56, 192, 45.14.5.238, 200, TCP_NC_MISS, 1123, 496, GET, http, c4.maxserving.com, /gen.js, ?site=5835&area=side_ros&group=sidebar&PageID=33364329499, -, DIRECT, c4.maxserving.com, application/x-javascript, "Mozilla/4.0, (compatible;, MSIE, 6.0;, Windows, NT, 5.1;, SV1;, .NET, CLR, 1.1.4322)", PROXIED, Web%20Advertisements, -, 192.16.170.44, SG-HTTP-Service, -, none, -)

scala> case class BlueCoatEvent(date: String,
     |                          time: String,
     |                          timeTaken: String,
     |                          cIp: String,
     |                          scStatus: String,
     |                          sAction: String,
     |                          scBytes: String,
     |                          csBytes: String,
     |                          csMethod: String,
     |                          csUriScheme: String,
     |                          csHost: String,
     |                          csUriPath: String,
     |                          csUriQuery: String,
     |                          csUsername: String,
     |                          sHierarchy: String,
     |                          sSupplierName: String,
     |                          rsContentType: String,
     |                          csUserAgent: String,
     |                          scFilterResult: String,
     |                          scFilterCategory: String,
     |                          xVirusId: String,
     |                          sIp: String,
     |                          sSiteName: String,
     |                          xVirusDetails: String,
     |                          xIcapErrorCode: String,
     |                          xIcapErrorDetails: String)
defined class BlueCoatEvent

scala> 

如何从s.split("\\s") 创建blueCoatEvent

【问题讨论】:

  • 我保证,使用有意义的类型会让你的生活变得更好。
  • 谢谢@TravisBrown,我同意,我会改变它们
  • 从名字上看,这几组似乎是相关的。可能那些应该有自己的 case classf es,而 blueCoatEvent 由它们中的每一个组成 + 剩下的任何东西

标签: scala


【解决方案1】:
  1. Instantiating a case class from a list of parameters中查看答案

  2. 引入有意义的子类型/案例类,并用它们组成BlueCoatEvent

【讨论】:

    【解决方案2】:

    丑陋可怕的方式是这样的:

    scala>   case class A(x: String, y: String, z: String)
    defined class A
    
    scala>   def toTuple[A <: Object](as:List[A]):Product = {
         |     val tupleClass = Class.forName("scala.Tuple" + as.size)
         |     tupleClass.getConstructors.apply(0).newInstance(as:_*).asInstanceOf[Product]
         |   }
    toTuple: [A <: Object](as: List[A])Product
    
    scala>   val l = List("a", "b", "c")
    l: List[String] = List(a, b, c)
    
    scala>   val t3 = toTuple(l).asInstanceOf[Tuple3[String, String, String]]
    t3: (String, String, String) = (a,b,c)
    
    scala>   val f = A.tupled
    f: ((String, String, String)) => A = <function1>
    
    scala>   f(t3)
    res0: A = A(a,b,c)
    

    您可以使用任何您想从集合转换为 TupleN 的方式:

    我从那里选择了toTuple

    这是不安全的,丑陋的,不会为您节省太多。您可以借助代码生成、反射或宏来获得更多帮助。

    另一种选择:

    基于Applying an argument list to curried function using foldLeft in Scala 这个想法,我们可以使用A.curriedHList 来产生更清洁的解决方案:

    object CaseClassFromList extends App {
    
      sealed trait HList
    
      final case class HCons[H, T <: HList](head : H, tail : T) extends HList {
        def ::[H1](h : H1) = HCons(h, this)
        override def toString = head+" :: "+tail.toString
      }
    
      trait HNil extends HList {
        def ::[H1](h : H1) = HCons(h, this)
        override def toString = "HNil"
      }
    
      case object HNil extends HNil
      type ::[H, T <: HList] = HCons[H, T]
    
    
      trait FoldCurry[L <: HList, F, Out] {
        def apply(l : L, f : F) : Out
      }
    
      // Base case for HLists of length one
      implicit def foldCurry1[H, Out] = new FoldCurry[H :: HNil, H => Out, Out] {
        def apply(l : H :: HNil, f : H => Out) = f(l.head)
      }
    
      // Case for HLists of length n+1
      implicit def foldCurry2[H, T <: HList, FT, Out]
      (implicit fct : FoldCurry[T, FT, Out]) = new FoldCurry[H :: T, H => FT, Out] {
        def apply(l : H :: T, f : H => FT) = fct(l.tail, f(l.head))
      }
    
      // Public interface ... implemented in terms of type class and instances above
      def foldCurry[L <: HList, F, Out](l : L, f : F)
                                       (implicit fc : FoldCurry[L, F, Out]) : Out = fc(l, f)
    
    
      case class A(x: String, y: String, z: String)
    
      //val l = List("a", "b", "c")
      val lh = "a" :: "b" :: "c" :: HNil
    
      val newA = foldCurry(lh, A.curried)
    
      println(newA)
    }
    

    问题再次是,除非您采用不安全的方式或某种代码生成,否则您无法避免拼出类型是 Tuple 还是 HList

    【讨论】:

      【解决方案3】:

      通过在事件的值上定义Map[String,String] 的不同方法;让

      case class EventMap( data: Map[String,String])
      

      def fields(cc: Product) = cc.getClass.getDeclaredFields.map(_.getName)
      

      然后从

      EventMap( fields(BlueCoatEvent) zip s.split("\\s") toMap )
      

      我们可以获取给定 stringized BlueCoatEvent 的值属性。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-05-08
        • 2019-09-30
        • 1970-01-01
        • 2020-03-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多