【问题标题】:How to instantiate a Scala object from a CSV/Map如何从 CSV/Map 实例化 Scala 对象
【发布时间】:2015-08-03 16:32:01
【问题描述】:

我目前正在编写一些 Scala 脚本。我有一个包含一些 Java 类的依赖库。

一个类看起来像这样:

public class Animal {
   protected String name;
   protected String animalBreed;

   public String getName() {
      return this.name;
   }

   public void setName(String value) {
      this.name = value;
   }

   public String getAnimalBreed() {
      return this.animalBreed;
   }

   public void setAnimalBreed(String value) {
      this.animalBreed = value;
   }
}

我有一些 CSV 输入文件,它们不一定包含类的所有字段,并且可能有一些其他未定义的字段。

例如:

name,age
Spyke,2

我已经有一些将 CSV 转换为 Map[String,String] 的代码。但我正在寻找一种“动态”实例化我的Animal 类的方法。动态地,我的意思是自动设置可用字段并跳过其他字段。在这种情况下,它将创建一个新的 Animal 对象,该对象具有名称但没有品种和年龄。

我真的不知道这在 Scala 中是否可行,或者什么关键字可以帮助我进行 Google 搜索——感谢任何帮助!

【问题讨论】:

  • 我建议对那些可能不存在的字段使用带有可选字段 (Option) 的案例类。在这种情况下,您可以使用 None 初始化不存在的字段,使用 Some(String) 初始化现有字段。

标签: java scala class csv


【解决方案1】:
import com.github.marklister.collections.io._
import com.github.marklister.collections._
Welcome to Scala version 2.11.6 (OpenJDK Server VM, Java 1.7.0_79).
Type in expressions to have them evaluated.
Type :help for more information.

scala> case class Animal (age: Option[Int], name:  Option[String],breed: Option[String])
defined class Animal

scala> val csv="""15,Cecil,Lion
     | 5,,Pangolin
     | n/a,Kermit,Frog"""
csv: String =
15,Cecil,Lion
5,,Pangolin
n/a,Kermit,Frog

scala> CsvParser(Animal).parse(new java.io.StringReader(csv))
res0: Seq[Animal] = List(Animal(Some(15),Some(Cecil),Some(Lion)), Animal(Some(5),None,Some(Pangolin)), Animal(None,Some(Kermit),Some(Frog)))

product-collections。很简单吧?

【讨论】:

  • 快速问题,如果 csv 的一个字段是我需要使用的类,是否可以解析它?类似 CsvParser(myFirstCol).parse(...)
  • 解析器默认使用these converters。定义自己的转换器相当简单——请查看文档。
【解决方案2】:

此 Scala 方法可以使用 Map[String,String] 中的字段创建 Animal Java 类的新实例。

  def createAnimal(fields: Map[String, String]): Animal =
    fields.foldLeft(new Animal) {
      (animal, field) => field._1 match {
        case "name" =>
          animal.setName(field._2)
        case "animalBreed" =>
          animal.setAnimalBreed(field._2)
        case _ =>
      }
      animal
    }

【讨论】:

  • 感谢您的回答,但这意味着我提前知道文件的顺序。您是否有任何现场订单的类似解决方案?例如,如果我有一个带有列的 csv:“年龄、姓名、动物品种”,那么您的解决方案将不起作用。谢谢
  • 顺序与我的解决方案无关。 foldLeft 将遍历 Map 中的字段,并在每个字段出现时应用一种或另一种情况。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-05
相关资源
最近更新 更多