【问题标题】:Scala. Arguments of nested lambdas with short syntax斯卡拉。语法短的嵌套 lambda 参数
【发布时间】:2013-11-23 20:01:10
【问题描述】:

请原谅我的英语:( 让我们通过例子来解释我的问题。我们有一个数组a

    var a = Array(1,1,1,1,2)

我们可以:

  1. 过滤a:

    a.filter( _ < 2 )
    
  2. 计算a中的一些元素:

    a.count (_ < 2)
    
  3. 获取集合中的唯一元素:

    a.filter { i =>
        a.count(_ == i) == 1
    }
    

问题是:如何在不引入变量i的情况下做第三个子句?是否可以写出类似的东西:

    a.filter ( a.count ( _ == __) == 1 )

我知道我可以写这个(而且还很短):

    a.filter { i => a.count(_ == i) == 1 }

但我只是对答案感兴趣。

【问题讨论】:

    标签: scala lambda functional-programming


    【解决方案1】:

    如果不引入变量 i 就无法做到这一点,因为它需要混合来自两个不同范围的变量(称为 closure)。如果我们在不使用_ 占位符变量的情况下编写此代码,则会变得更加清晰。

    a.filter( outer =>
      a.count( inner =>
        outer == inner
      ) == 1
    )
    

    对于a 中的每个outer 值,我们正在创建一个新函数以传递给count,其中outer 是常量,inner 作为参数传入。 _ 只能作为它所在的最内层函数的占位符,因此不能用于替换outer。这就是为什么

    a.filter( outer =>
      a.count(
        outer == _
      ) == 1
    )
    

    编译但是

    a.filter(
      a.count( inner =>
        _ == inner
      ) == 1
    )
    

    没有。

    【讨论】:

      【解决方案2】:

      只是提到一个替代解决方案(我想不是更简单,但更快)

      a.groupBy(identity).filter{ case (_, v) => v.size == 1}.keys
      

      【讨论】:

      • xs groupBy identity collect { case (k, v) if v.size == 1 =&gt; k }
      • 或者(甚至更快、更复杂):a.foldLeft(collection.mutable.Map[Any, Int]().withDefaultValue(0))((m, x) =&gt; { m(x) += 1; m }).filter(_._2 == 1).keys。不过,实际上只有 70 个或更多元素的列表才会更快。
      猜你喜欢
      • 2021-06-09
      • 1970-01-01
      • 1970-01-01
      • 2017-10-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-14
      • 2011-05-21
      相关资源
      最近更新 更多