提取集合
|
最近,我为Anys的笛卡尔乘积编写了一个迭代器,并从List列表开始,但认识到我可以轻松切换到更抽象的特征Seq。
我知道,您喜欢看代码。 :)
class Cartesian (val ll: Seq[Seq[_]]) extends Iterator [Seq[_]] {
def combicount: Int = (1 /: ll) (_ * _.length)
val last = combicount
var iter = 0
override def hasNext (): Boolean = iter < last
override def next (): Seq[_] = {
val res = combination (ll, iter)
iter += 1
res
}
def combination (xx: Seq [Seq[_]], i: Int): List[_] = xx match {
case Nil => Nil
case x :: xs => x (i % x.length) :: combination (xs, i / x.length)
}
}
和该类别的客户:
object Main extends Application {
val illi = new Cartesian (List (\"abc\".toList, \"xy\".toList, \"AB\".toList))
// val ivvi = new Cartesian (Vector (Vector (1, 2, 3), Vector (10, 20)))
val issi = new Cartesian (Seq (Seq (1, 2, 3), Seq (10, 20)))
// val iaai = new Cartesian (Array (Array (1, 2, 3), Array (10, 20)))
(0 to 5).foreach (dummy => println (illi.next ()))
// (0 to 5).foreach (dummy => println (issi.next ()))
}
/*
List(a, x, A)
List(b, x, A)
List(c, x, A)
List(a, y, A)
List(b, y, A)
List(c, y, A)
*/
该代码适用于Seq和List(它们是Seqs),但是当然不适用于数组或Vector,它们不是Seq类型,并且没有约束方法\':: \'。
但是逻辑也可以用于此类集合。
我可以尝试为Vector,Array等编写与Seq之间的隐式转换,或者尝试编写自己的类似实现,或者编写Wrapper,将包装转换为Seq的Seq,然后调用\'hasNext内部集合的\'和\'next \',并将结果转换为Array,Vector或其他任何形式。 (我尝试实现这种解决方法,但我必须认识到:这并不容易。对于现实世界中的问题,我可能会独立地重写Iterator。)
但是,如果我必须处理列表数组或数组列表以及其他混合情况,那么整个事情就会失去控制。
用最广泛,可能的方式编写算法的最优雅方法是什么?
没有找到相关结果
已邀请:
1 个回复
怪酞撩匹
这类作品:
由于错误https://issues.scala-lang.org/browse/SI-3343,我需要显式传递类型 需要注意的一件事是,这比使用存在类型更好,因为在迭代器上调用next返回正确的类型,而不是Seq [Any]。 这里有几个缺点: 如果容器不是所需类型的子类,则将其转换为一个,这会降低性能 该算法不是完全通用的。我们只需要使用这些类型提供的功能子集将类型转换为SeqLike或TraversableLike。因此,制作转换函数可能很棘手。 如果某些功能可以在不同的上下文中进行不同的解释怎么办?例如,一个矩形具有两个\'length \'属性(宽度和高度) 现在为替代解决方案。我们注意到,我们实际上并不关心集合的类型,而只是关心它们的功能: TT应该有
,
(头/尾) ST应该有
,
和一个Builder 所以我们可以对它们进行编码:
(严格来说,HasFold不是必需的,因为它的实现是基于长度和获取的,但是我在这里添加了它,以便算法可以更清晰地转换) 现在的算法是:
并使用:
Scalaz可能已经为您提供了所有预定义的功能,但不幸的是,我不太了解。 (再次,我需要传递类型,因为推断不能推断正确的种类) 好处是该算法现在是完全通用的,并且不需要从Array到WrappedArray的隐式转换即可运行 锻炼:为元组定义;-)