映射在视图上的函数列表 - 视图是不是被多次遍历?

Posted

技术标签:

【中文标题】映射在视图上的函数列表 - 视图是不是被多次遍历?【英文标题】:List of functions mapped on view - is the view traversed more than once?映射在视图上的函数列表 - 视图是否被多次遍历? 【发布时间】:2013-11-15 12:48:06 【问题描述】:

我正试图围绕如何在 Scala 中使用视图。我有以下示例代码:

class Square extends (Seq[Int] => Int) 
    def apply(x: Seq[Int]) = x.reduce(_ * _)


class Sum extends (Seq[Int] => Int) 
    def apply(x: Seq[Int]) = x.reduce(_ + _)


val functionList = List(new Square, new Sum)

val list = List(1, 2, 3, 4, 5, 6)
val view = list.view

functionList.map(f => f(view))

我的问题是:

    上例中应用地图时,列表会被遍历一次还是两次? 如果遍历不止一次,是否有任何其他设计模式可以让我定义函数集合并映射到其他集合,同时只遍历第二个集合一次?

【问题讨论】:

【参考方案1】:

列表被遍历了两次。您实际上要做的是首先使用Square 函数并在所有元素上应用reduce。接下来,Sum 函数还将对所有元素应用reduce

视图将集合变成惰性集合。这意味着如果您有多个转换,它们只会在需要时应用。在这种情况下,我认为这对您的解决方案没有任何影响,因为您正在应用对整个集合进行计算的函数(这意味着需要对它们进行评估以获得结果)。有关何时使用视图的答案,请参阅 this question。


在这种情况下,遍历第二个集合并不容易。您有两个函数在整个列表中执行 reduce,这意味着每个函数都需要一个 单独的累加器 并具有单独的结果。如果你只想遍历你的元素列表一次,你需要稍微改变你的逻辑。您需要定义关于如何组合两个元素的操作,而不是定义对整个列表的操作。这是我想出的:

val functionListWithInitialValues = List(
  ((a: Int, b: Int) => a * b, 1), //This is a Tuple that defines how to combine two calculations and what the initial value is.
  ((a: Int, b: Int) => a + b, 0)
)

val results = list.foldLeft(functionListWithInitialValues) 
  case (accumulators, next) => // foldLeft gives us the previous results
                               // (which is essentailly a Tuple(function, value)),
                               // and the next element, to combine with the previous result.
    // Now let's go through our functions and apply the functions on the accumulator and the next element
    accumulators.map 
      case (function, previousResult) =>
        (function, function(previousResult, next))
    

results.map  case (function, result) => println(result) 

这个解决方案只会遍历你的元素一次,对累加器和下一个元素应用组合函数。

【讨论】:

【参考方案2】:

不确定您在说什么列表。

您正在将映射应用于实际的严格列表,因此 functionList 将被遍历一次,并且将“f”应用于视图将减少 functionList 中每个函数的 List[Int]。

如果你想懒惰地应用你的修改器,那么 functionList 应该是一个视图,这样 'map' 就不严格了。

【讨论】:

以上是关于映射在视图上的函数列表 - 视图是不是被多次遍历?的主要内容,如果未能解决你的问题,请参考以下文章

警报视图显示多次而不是一次

在 CodeIgniter 3 中多次渲染视图

多次调用getView方法

带有适配器的 Android 列表视图仅显示第一项(多次)

如何遍历地图列表并在颤动列表视图中显示文本小部件?

Swift 3:通过遍历视图数组来设置视图