【问题标题】:Scala split string to tupleScala将字符串拆分为元组
【发布时间】:2013-02-04 23:38:23
【问题描述】:

我想在包含 4 个元素的空格上拆分一个字符串:

1 1 4.57 0.83

我正在尝试转换为 List[(String,String,Point)] 以便前两个拆分是列表中的前两个元素,后两个是 Point。我正在执行以下操作,但它似乎不起作用:

Source.fromFile(filename).getLines.map(string => { 
            val split = string.split(" ")
            (split(0), split(1), split(2))
        }).map{t => List(t._1, t._2, t._3)}.toIterator

【问题讨论】:

  • 如果你想要一个元组,为什么要转换成一个列表?
  • 我同意,这应该更接近于将字符串转换为 List() 元素

标签: string list scala split tuples


【解决方案1】:

您没有将第三个和第四个标记转换为Point,也没有将这些行转换为List。此外,您不会将每个元素呈现为 Tuple3,而是呈现为 List

以下内容应该更符合您的要求。

case class Point(x: Double, y: Double) // Simple point class
Source.fromFile(filename).getLines.map(line => { 
    val tokens = line.split("""\s+""") // Use a regex to avoid empty tokens
    (tokens(0), tokens(1), Point(tokens(2).toDouble, tokens(3).toDouble))
}).toList // Convert from an Iterator to List

【讨论】:

  • 我的 Point 类需要 (IndexedSeq[Double]) 那么如何从元组中获取 Indexed Seq?
【解决方案2】:

您可以使用模式匹配从数组中提取您需要的内容:

    case class Point(pts: Seq[Double])
    val lines = List("1 1 4.34 2.34")

    val coords = lines.collect(_.split("\\s+") match {
      case Array(s1, s2, points @ _*) => (s1, s2, Point(points.map(_.toDouble)))
    })

【讨论】:

  • 这不会为我编译,我添加了另一个类似的编译答案 - 我无法让代码在 cmets 中正确显示。如果其他人知道,我很想知道如何使用 collect。
  • 来自collect的API “通过将部分函数应用于此列表中定义函数的所有元素来构建新集合。”。它就像map,但只留下偏函数域中的元素
【解决方案3】:

这个怎么样:

scala> case class Point(x: Double, y: Double)
defined class Point

scala> s43.split("\\s+") match { case Array(i, j, x, y) => (i.toInt, j.toInt, Point(x.toDouble, y.toDouble)) }
res00: (Int, Int, Point) = (1,1,Point(4.57,0.83))

【讨论】:

  • 简单明了。您可能需要添加一个案例来处理输入错误。
【解决方案4】:

有多种方法可以将 Tuple 转换为 List 或 Seq,一种方法是

scala> (1,2,3).productIterator.toList
res12: List[Any] = List(1, 2, 3)

但是你可以看到返回类型是 Any 而不是 INTEGER

为了转换成不同的类型,你使用 Hlist https://github.com/milessabin/shapeless

【讨论】:

    【解决方案5】:
    case class Point(pts: Seq[Double])
    val lines = "1 1 4.34 2.34"
    
    val splitLines = lines.split("\\s+") match {
      case Array(s1, s2, points @ _*) => (s1, s2, Point(points.map(_.toDouble)))
    }
    

    对于好奇,模式匹配中的 @ 将变量绑定到模式,因此 points @ _* 将变量点绑定到模式 *_ 并且 *_ 匹配数组的其余部分,因此 points 最终成为序列[字符串]。

    【讨论】:

    • 嗯.. 我得到 scala.MatchError: [Ljava.lang.String;@7bfacd5d (of class [Ljava.lang.String;) 我做错了什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-12
    • 2012-02-22
    • 2011-06-30
    • 1970-01-01
    相关资源
    最近更新 更多