如何在scala中编写元组范围函数?
我想要以下功能 range((1,1), (2,2))
其返回值
Seq[(Int,Int)]((1,1),(1,2),(2,1),(2,2))
与 1 到 2
的一维范围类似
该函数应该适用于任何 scala 元组 (即 Tuple2、Tuple3、Tuple4,...)并且类型安全。
我尝试过
def tupleRange[T <: Product](t1:T, t2:T):Seq[T] = {
assert(t1.productArity == t2.productArity)
def tail(t:Product):Product = sys.error("todo");
def join(i:Int, p:Product):T = sys.error("todo");
for(
v <- t1.productElement(0).asInstanceOf[Int] to t2.productElement(0).asInstanceOf[Int];
v2 <- tupleRange(tail(t1), tail(t2)))
yield join(v,v2)
}
implicit def range[T <:Product](p1:T) = new { def to(p2:T) = tupleRange(p1,p2)}
但我认为我选择了错误的方向。
I want following functionrange((1,1), (2,2))
which return
Seq[(Int,Int)]((1,1),(1,2),(2,1),(2,2))
It is analog for one dimensional range with 1 to 2
The function should work for any scala tuple (i.e. Tuple2, Tuple3, Tuple4, ...) and be typesafe.
I've tried with
def tupleRange[T <: Product](t1:T, t2:T):Seq[T] = {
assert(t1.productArity == t2.productArity)
def tail(t:Product):Product = sys.error("todo");
def join(i:Int, p:Product):T = sys.error("todo");
for(
v <- t1.productElement(0).asInstanceOf[Int] to t2.productElement(0).asInstanceOf[Int];
v2 <- tupleRange(tail(t1), tail(t2)))
yield join(v,v2)
}
implicit def range[T <:Product](p1:T) = new { def to(p2:T) = tupleRange(p1,p2)}
But I think I've chosen wrong direction.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我建议和@ziggystar 上面建议的一样。使用
List[Int]
而不是Int
的元组。此实现假设
xs
和ys
是有序的并且具有相同的长度。I'd suggest the same thing that @ziggystar suggested above. Use
List[Int]
instead of tuples ofInt
s.This implementation assumes that
xs
andys
are ordered and have same length.首先,考虑一下:
为元组提供类似的东西会很好,对吧?
这将为您提供以下信息:
这对您有用吗?
First, consider this:
It'd be nice to have something like that for Tuples, right?
This gives you the following:
Does that work for you?
每个元组数量都需要不同的版本(但您可以使用预处理器来生成每个版本)。这是我的实现(这是懒惰的):
您可以将其用作:
You'll need a different version for each tuple-arity (but you can use a preprocessor to generate each version). Here is my implementation (which is lazy):
You can use it as:
使用大量剪切和粘贴的简单方法,为每个元组重载方法:
或者:
似乎可行:
你的基本问题是,由于 Scala 是静态类型的,该方法需要有一个返回类型,因此你永远不能有一个返回类型返回 Seq[(Int, Int)] 和 Seq[(Int, Int, Int)] 以及元组的所有其他参数的方法。您能做的最好的事情就是使用涵盖所有输出的最接近的类型,在本例中为
Product with Serialized
。您当然可以对结果进行转换,例如res0.map(_.asInstanceOf[(Int, Int, Int)])
。如第一个示例中那样重载该方法允许您为每个数量使用不同的返回类型,因此您不需要进行任何转换。
Simple way with lots of cut and paste, overload the method for each tuple arity:
Alternatively:
seems to work:
Your basic problem is that since Scala is statically typed, the method needs to have a return type, so you can never have a single method that returns both a
Seq[(Int, Int)]
and aSeq[(Int, Int, Int)]
and all the other arities of tuple. The best you can do is to use the closest type that covers all of the outputs, in this caseProduct with Serializable
. You can of course do a cast on the result e.g.res0.map(_.asInstanceOf[(Int, Int, Int)])
.Overloading the method as in the first example allows you a different return type for each arity, so you don't need to do any casting.
一个迭代器,并使用两个 Seq 而不是两个元组进行初始化怎么样?
这是一个 Cartesian 类,它扩展了 Iterator。
用法:
How about an Iterator, and using two Seq instead of two tuples for initialization?
Here is a class Cartesian, which extends Iterator.
usage: