Scala将具有未知长度的List转换为Tuple,因此将其传递给Slick map子句

时间:2017-01-13 14:38:45

标签: scala list tuples slick

我在scala代码中有List,例如我可以从特定方法接收,此列表的长度可能会不时变化,我的目标是将此List转换为{{1}具有相同的元素数:

Tuple

澄清

val lst = someComputationHere()
val tupleLst = lstToTuple(lst)

P.S。我宁愿不使用反射解决这个问题

UPD 我的目标是带有上述属性的通过列表,发送到//if lst.length = 2 --> Tuple2 //if lst.length = 3 --> Tuple3 //if lst.length = 4 --> Tuple4 ............... //if lst.length = N --> TupleN and so on Slick。让我们考虑下一个代码快照:

map clause

此值的数量是dinamic,我将此query.map{ p=> (p.value1, p.value2, ... , p.valueN)} 引入列表:

values

问题描述 val lst = someComputationHere() val tuples = toTuples(lst)//Problem is here query.map{_ => tuples} - 没有通过列表,作为后果,我必须将query.map{}的长度N更改为lst有N个元素

2 个答案:

答案 0 :(得分:2)

我不知道Slick,但如果它只处理元组,那对我来说似乎是一个糟糕的设计选择。即使在Scala 2.12中,对于大于22的arity元组也没有预定义类型,尽管Scala将合成创建它们。所以你最好的选择是一个大模式匹配,包括你需要支持的所有arities:

def toTuple[A](lst: List[A]): Product = lst match {
  case _1 :: Nil             => Tuple1(_1)
  case _1 :: _2 :: Nil       => Tuple2(_1, _2)
  case _1 :: _2 :: _3 :: Nil => Tuple3(_1, _2, _3)
  ...
}

答案 1 :(得分:0)

通常,您无法执行此操作,因为元组访问方法_1_2等具有编译时检查(列表大小在编译时未定义)。但是所有元组都实现了Product trait,你可以按顺序获取元素:

(1, 2, 3).productElement(2) // returns 2

您可以尝试使用下一个签名(可能使用宏)编写方法

List[T] => Product

方法将返回TupleN,其中N是列表大小。例如,非常原始的实现:

list.length match {
  case 1 => (list(0))
  case 2 => (list(0), list(1))
  ...
  case 22 => (list(0), list(1), ... ,list(21))
  case _ => throw some exception...
}

在运行时之后,您可以尝试将产品转换为具体的TupleN类型。但这一切看起来都很脏。