我有一个扩展Iterator并为复杂算法建模的类(MyAlgorithm1)。因此,该算法可以逐步推进Next方法。
class MyAlgorithm1(val c:Set) extends Iterator[Step] {
override def next():Step {
/* ... */
}
/* ... */
}
现在我想在第一个算法的每次传递中应用不同的算法(MyAlgorithm2)。应插入算法1和2的迭代
class MyAlgorithm2(val c:Set) { /* ... */ }
我怎样才能以最好的方式做到这一点?也许有一些特质?
更新
MyAlgorithm2收集一个集并对其进行转换。 MyAlgorithm1也是,但这更复杂,必须一步一步地运行。这个想法是运行MyAlgoirthm1的一步,然后运行MyAlgorithm2。下一步一样。实际上,MyAlgorithm2简化了集合,可能有助于简化MyAlgorithm1的工作。
答案 0 :(得分:4)
如上所述,问题可以通过继承或特征来解决。例如:
class MyAlgorithm1(val c:Set) extends Iterator[Step] {
protected var current = Step(c)
override def next():Step = {
current = process(current)
current
}
override def hasNext: Boolean = !current.set.isEmpty
private def process(s: Step): Step = s
}
class MyAlgorithm2(c: Set) extends MyAlgorithm1(c) {
override def next(): Step = {
super.next()
current = process(current)
current
}
private def process(s: Step): Step = s
}
对于特征,您可以使用abstract override
执行某些操作,但设计它以便将简化的结果提供给第一个算法可能会更难。
但是,我建议你以错误的方式解决问题。
您可以像下面这样定义算法,而不是为扩展迭代器的算法创建类:
class MyAlgorithm1 extends Function1[Step, Step] {
def apply(s: Step): Step = s
}
class MyAlgorithm2 extends Function1[Step, Step] {
def apply(s: Step): Step = s
}
然后可以更容易地定义迭代器:
Iterator.iterate(Step(set))(MyAlgorithm1 andThen MyAlgorithm2).takeWhile(_.set.nonEmpty)
答案 1 :(得分:2)
扩展Iterator可能比您实际需要做的更多。让我们回滚一下。
你有一些MyAlgorithm1
类型的有状态对象val alg1 = new MyAlgorithm1(args)
现在你希望重复调用它上面的一些函数,它会改变它的状态并返回一些值。最好不要让对象实现Iterator,而是通过创建一个处理迭代的新对象来建模。可能Scala标准库中最简单的一个是Stream。这是一个从算法中创建结果流的对象。
val alg1Stream:Stream[Step] = Stream.continually(alg1.next())
现在,如果您想重复从该流中获取结果,那么就像
一样简单for(step<-alg1Stream){
// do something
}
或等效
alg1Stream.forEach{
//do something
}
现在假设我们还将myAlgorithm2封装为流
val alg2=new MyAlgorithm2(args)
val alg2Stream:Stream[Step] = Stream.continually(alg2.next())
然后我们只需要一些方法来交错流,然后我们可以说
for(step<-interleave(alg1Stream, algStream2)){
// do something
}
可悲的是,快速浏览一下标准库,就没有显示Stream交错功能。很容易写一个
def interleave[A](stream1:Stream[A], stream2:Stream[A]):Stream[A] ={
var str1 = stream1
var str2 = stream2
var streamToUse = 1
Stream.continually{
if(streamToUse == 1){
streamToUse = 2
val out = str1.head
str1 = str1.tail
out
}else{
streamToUse = 1
val out = str2.head
str2 = str1.tail
out
}
}
}
构造一个在两个流之间重复交替的流,从适当的流中获取下一个结果,然后为下一次获取设置它的状态。请注意,此交错仅适用于无限流,并且我们需要一个更聪明的流来处理可以结束的流,但这样可以解决问题。
答案 2 :(得分:1)
我有一个扩展Iterator并为复杂算法建模的类(MyAlgorithm1)。
好吧,在那里停一会儿。算法不是迭代器,因此扩展Iterator
没有意义。
答案 3 :(得分:1)
似乎您可能想要使用折叠或地图,具体取决于您想要做什么。这是函数式编程中的常见模式:生成某个列表/序列/流,然后对每个元素运行一个函数。如果要在每个元素上运行两个函数,可以编写函数或运行另一个映射。