我有一个我foldLeft
来收集另一个集合的集合。我使用所需类型的空集合初始化foldLeft
。
collection1.foldLeft(collection[T]())(op)
我的第一个测试测试fold
操作中的集合是否为空,然后如果是,则从fold
ed集合中创建一个集合。
collection1.foldLeft(collection[T]())({
{ case(t,otherstuff) =>
if(t.isEmpty) new T(otherstuff) else ...}
})
看到我是如何初始化一个空集合并总是抛弃它,是否可以在初始化阶段创建初始集合(对空集合的响应)?
collection1.foldLeft(new T(collection1.first))({ // but SKIP first
{ case(t,otherstuff) =>
...}
})
答案 0 :(得分:0)
这主要是让我觉得一个坏主意,你用一个空集合初始化累加器的原因是你可以统一操作,即通常你没有像if(t.isEmpty) ... else ...
这样的特殊情况逻辑
我不知道你的应用程序,所以让我们假设你真的需要这样做,无论你在普通操作中做什么,都需要一个非空的Collection,它必须首先用一个包含第一次遇到元素,但之后必须以不同的方式运作。
首先要指出的是,您现有的方法可能并不可怕。您正在努力消除一个对象分配,这不太可能是性能瓶颈。 “过早的优化是所有邪恶的根源”,sez Donald Knuth。
要指出的第二点是,你通常不应该在scala中创建一个空集合collection[T]()
。如果collection
代表某个集合类或特征的名称,则可能有一个类似collection.empty[T]
的方法,它每次都提供一个没有新分配的空实例。所以最简单的优化只是......
collection1.foldLeft(collection.empty[T])({
{ case(t,otherstuff) =>
if(t.isEmpty) new T(otherstuff) else ...}
})
如果collection
代表其伴侣不提供空方法的某个自定义不可变集合类,请在集合的伴随对象中定义一个(如果可以的话),如果不能,则在别处定义。
private val emptyCollection = collection[Nothing]()
def empty[T] : collection = emptyCollection.asInstanceOf[T]
如果您确定折叠的集合将包含至少一个元素,则每次都可以避免空检查:
val pair = collection1.splitAt(1)
pair._2.foldLeft(pair._1){(col, next) =>
...
}
...
是原始空检查的else
个案例,不再需要if
。为了做到这一点,将其包装在测试中
if ( !collection1.isEmpty ) {
val pair = collection1.splitAt(1)
pair._2.foldLeft(pair._1){(col, next) =>
...
}
} else {
appropriateDefaultResult
}
答案 1 :(得分:0)
您真的不想使用fold
来产生另一个集合。折叠本质上是一种变异reduce
。 reduce
使用some value in the collection as a starting point来累积值,并且为designed specifically for a commutative and associative operation on a collection。 fold
操作缺少这两个约束,但它们不能拆分为并发操作,因为每个累积必须按顺序发生。
是否有理由认为标准的循环列表推导不适合你?