2013-10-27 27 views
57

当以后应用像map,flatmap等函数时,使用filter而不是filter是否总是更高效?withFilter而不是过滤器

为什么只支持map,flatmap和foreach? (像forall这样的预期功能也存在)

回答

93

the Scala docs

注:区别c filter pc withFilter p之间的区别在于前者 创建了一个新的集合,而后者仅限制了的域后续map,flatMap,foreachwithFilter操作。

所以filter将原来的收集和产生一个新的集合,但withFilter将非严格(即懒洋洋地)到后来map/flatMap/withFilter调用传递未过滤的值,节省通过(过滤第二遍)集合。因此,在传递给这些后续的方法调用时它会更高效。

实际上,withFilter是专门设计用于处理这些方法的链,这是理解被去除的东西。此方法不需要其他方法(如forall/exists),因此它们尚未被添加到FilterMonadic返回类型withFilter

+0

希望他们仍然增加这些方法的一些日子。 – Kigyo

+1

@Kigyo我不认为你应该自己使用Filter(除了隐含在for表达式之外)。如果你想要地图/过滤器是懒惰的,请使用'view'。 –

+0

我明白了。 'view'和'withFilter'之间的确切区别是什么?为什么不是用于'for-loops'的视图? – Kigyo

-5

作为一种解决方法,您只能使用mapflatMap来实现其他功能。

而且,这种优化是小集合没用......

-3

使用对产量可周围的工作,例如:

for { 
    e <- col; 
    if e isNotEmpty 
} yield e.get(0) 
2

此外,the excellent answer of Shadowlands,我想带一个直观的例子,filterwithFilter之间的区别。

让我们看看下面的代码

val list = List(1, 2, 3) 
var go = true 
val result = for(i <- list; if(go)) yield { 
    go = false 
    i 
} 

大多数人期待result等于List(1)。这是自斯卡拉2.8的情况下,由于换理解被翻译成

val result = list withFilter { 
    case i => go 
} map { 
    case i => { 
    go = false 
    i 
    } 
} 

正如你可以看到翻译的条件转换成以withFilter通话。在此之前的Scala 2.8,换理解被翻译成类似以下内容:

val r2 = list filter { 
    case i => go 
} map { 
    case i => { 
    go = false 
    i 
    } 
} 

使用filterresult值将是相当不同的:List(1, 2, 3)。事实上,我们使go标志false对过滤器没有影响,因为过滤器已经完成。再次,在Scala 2.8中,这个问题使用withFilter来解决。当使用withFilter时,每次在map方法内访问元素时都会评估条件。

参考: - 第120页,斯卡拉在行动(包括斯卡拉2.10),曼宁出版物,Milanjan Raychaudhuri - Odersky's thoughts about for-comprehension translation

相关问题