【问题标题】:How to perform pattern matching with vararg case classes?如何使用可变参数案例类执行模式匹配?
【发布时间】:2011-01-17 12:09:13
【问题描述】:

我有一组这样的案例类

abstract class Shape  
case class Rectangle(width: Int, height: Int) extends Shape  
case class Location(x: Int, y: Int, shape: Shape) extends Shape  
case class Circle(radius: Int) extends Shape  
case class Group(shape: Shape*) extends Shape

Group 基本上是一个形状数组。我需要定义一个计算尺寸的尺寸方法 对于矩形、圆形和位置,它直接返回一个。但我对集团有困难。

object size extends Shape{  
  def size(s: Any) : Int = s match {  
    case Rectangle(x,y) => 1  
    case Group  // how to do it? Also having case Group(shape : Shape*) gives an error  
    case Circle(r) => 1    
    case Location(x,y,shape) => 1   
  }  
}  

我知道对于 Group,我需要使用 map 并左折叠,但我真的无法为其创建逻辑。 谢谢

【问题讨论】:

    标签: scala functional-programming pattern-matching


    【解决方案1】:

    可变参数模式匹配的语法有点像strange

    def size(s: Shape) : Int = s match{
      case Rectangle(x,y) => 1
      case Circle(r) => 1
      case Location(x,y,shape) => 1
      case Group(shapes @ _*) => (0 /: shapes) { _ + size(_) }
    }
    

    请注意,在最后一行中,您使用 /:-notation 表示所有从零开始的子shapes 的大小。


    folds 的工作原理:折叠使用给定函数累积序列的元素。

    因此,为了计算列表的总和,我们将编写(Haskell 风格)

    fold (\total element -> total + element) 0 list
    

    它将列表中的所有元素与从 0 开始的给定加法函数组合起来(因此计算总和)。

    在 Scala 中,我们可以这样写:

    (0 /: list) { (total, element) => total + element }
    

    可以简化为

    (0 /: list) { _ + _ }
    

    【讨论】:

    • 这不考虑重叠。这有关系吗?
    • 你能解释一下最后一行的工作方式太奇怪了吗????? case Group(shapes @ *) => (0 /: shapes) { _ + size() }
    • @PanCrit:我对 Scala 不是很流利 - 请您解释一下 overlap 是什么意思?
    • @tom @ 符号的意思是“将与我右侧模式匹配的任何内容分配给我左侧的标识符”。例如,r @ Rectangle(x, y) 会将整个Rectangle 分配给r,并将其分解分配给xy。现在,_* 模式只是意味着“任意数量的任何东西”。
    • @Dario 我想 PanCrit 是说你不能只添加所有形状的大小,因为它们可能会重叠。那么,联合的大小将小于所有大小的总和。
    【解决方案2】:

    其中任何一个都可以,如果乍一看有点奇怪,第二个可能是首选。请参阅Scala Reference 中的 8.1.9 模式序列。

    case g: Group => g.shape.map(size(_)).sum
    
    case Group(ss @ _*) => ss.map(size(_)).sum
    

    这是使用 Scala 2.8。 sum 可能不适用于旧版本。

    【讨论】:

    • 这不考虑重叠。这很重要吗?
    • 我的假设是问题是关于 Scala 中的模式匹配而不是几何。
    【解决方案3】:

    第一步是弄清楚你的意思。两个最明显的选择是所有形状覆盖的总面积,以及包含所有形状的最小矩形。如果对于圆圈,您返回实际区域,那么您可能必须使用实际区域。

    没有封闭式的方式来回答这个问题。我可能会考虑在最小的封闭矩形上投掷一千个随机飞镖,并将该区域估计为击中占据点的飞镖的百分比。估计值是可接受的响应吗?

    你能保证所有的形状都是圆形和矩形吗?您也许可以拼凑出一个适合他们的解决方案。如果 Shapes 可以进一步扩展,那就行不通了。

    【讨论】:

      【解决方案4】:

      case g: Group => g.shape.map(size(_)).sum

      案例组(ss@*) => ss.map(size()).sum

      这两个都给出了错误值 sum is not a member of Seq[Int]
      但是这个oen有效
      案例组(形状@_*)=>(0 /:形状){_+大小(_)

      【讨论】:

      • 请不要将问题作为答案发布,而是编辑您的问题!
      【解决方案5】:

      对于位置大小,应向下钻取以获取大小,因为形状可能是组,这会导致更高的计数

      case Location(x,y,shape) => size(shape)

      也就是说,如果 size 是 Shape 中形状的数量

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-07-15
        • 1970-01-01
        • 2017-02-25
        • 1970-01-01
        • 2017-04-25
        • 2013-11-28
        • 2012-01-02
        • 1970-01-01
        相关资源
        最近更新 更多