0

我是 Scala 的新手,一般来说真的是编码很抱歉,如果这个问题有点基本,但希望得到一些帮助!

我目前有一个产生的函数,Seq[(String, String)]然后我想将其转换为Seq[String].

根据函数的迭代,向量的维度会有所不同,所以有些结果是Seq[(String, String)],其他的Seq[(String, String, String)]等等。所以理想情况下,我可以对每个输出使用相同的函数。

我尝试过使用.flatten,并且split[","]不确定我可以使用哪些其他方法。

对于一个样本值,函数的输出如下所示:

res17: Seq[(String, String)] = Vector((u, v),(w, x))

理想的结果是Vector(u,v,w,x)

4

2 回答 2

1

考虑无形的方法,它提供了一种以类型安全的方式抽象的方法:

import shapeless._
import shapeless.ops.hlist
import syntax.std.tuple._

def flattenTupleN[P <: Product, L <: HList](
  ps: List[P]
)(implicit gen: Generic.Aux[P, L],
  toT: hlist.ToTraversable.Aux[L, List, String]
): List[String] = {
  ps.flatMap(p => gen.to(p).toList) 
}

val t1: List[(String, String)] = List(("u", "v"), ("w", "x"))
val t2: List[(String, String, String)] = List(("a", "b", "c"), ("d", "e", "f"))
val t3: List[(Int, Double, String)] = List((42, 3.14, "Picard"))

flattenTupleN(t1)
flattenTupleN(t2)
// flattenTupleN(t3) // compile-time error

哪个输出

res0: List[String] = List(u, v, w, x)
res1: List[String] = List(a, b, c, d, e, f)

这是一种不安全但开箱即用的方法:

def flattenTupleNUnsafe(ps: List[Product]): List[String] =
  ps.flatMap(_.productIterator.map(_.toString))

flattenTupleNUnsafe(t1)
flattenTupleNUnsafe(t2)
flattenTupleNUnsafe(t3) // compiles OK but is a bad idea!

哪个输出

res2: List[String] = List(u, v, w, x)
res3: List[String] = List(a, b, c, d, e, f)
res4: List[String] = List(42, 3.14, Picard)

请注意,由于类型安全性的丢失,如何flattenTupleNUnsafe(t3)编译得很好,并在程序中引入了逻辑错误。

于 2019-10-13T12:20:32.283 回答
0

我同意那些询问有关您的用例的更多信息的人的观点。如果不了解更多关于您尝试转换的数据的信息,就很难推荐一个简洁的解决方案来满足您的需求。

请暂时考虑一下我要说的话,因为我对您要做什么还不够了解。

你说你输出的元组可以变化。您是否考虑过将所有内容从 Tuple 转换为 Vector?

所以而不是

res17: Vector[(String, String)] = Vector((u, v),(w, x))

利用

res17: Vector[Vector[String]] = Vector(Vector(u, v),Vector(w, x))

然后,您可以通过调用 flatMap 或 flatten 轻松地将 Vector 的 Vector 转换为单个 Vector,根据您的问题,听起来您已经知道该怎么做。

我从阅读您的问题中得到的另一个印象是,如果您想保留从该参数列表转换为向量的固定长度参数列表,您可能需要查看案例类而不是元组。

因此,不要定义Tuple2or Tuple3,而是定义一个允许编译器对您的程序进行类型检查的继承层次结构。

像这样的东西:

trait MyData

case class 2MemberData(data1: String, data2: String) extends MyData

case class 3MemberData(data1: String, data2: String, data3: String) extends MyData

case class 4MemberData(data1: String, data2: String, data3: String, data4: String) extends My Data

这样,您的函数可以输出 Vector[MyData] 类型的值,然后您可以使用模式匹配将其展平。所以像

def processData: Vector[MyData]

def cleanUp(input: Vector[MyData]): Vector[String]

其中 cleanUp 实现如下:

def cleanUp(input: Vector[MyData]): Vector[String] = {
  input.flatMap{ d =>
    d match {
      case 2MemberData(data1, data2) => Vector(data1, data2)
      case 3MemberData(data1, data2, data3) => Vector(data1, data2, data3)
      case 4MemberData(data1, data2, data3, data4) => Vector(data1, data2, data3, data4)
    }
  }
}

我只是把想法扔在那里,不知道我所说的是否有帮助。这实际上取决于周围的代码是什么样的。如果您有任何问题随时问。

于 2019-10-13T19:33:39.373 回答