【问题标题】:Pattern matching in lists that contain case classes包含案例类的列表中的模式匹配
【发布时间】:2012-04-24 09:34:27
【问题描述】:

this topic 的序列中,我正在开发一个允许将块组合到scala 的系统,因此我可以使用模式匹配来创建重写规则系统。

但是我被卡住了。

我有这些课程:

abstract class Block(n: String, in: List[Input], out: List[Out]){
  def name = n; def outputs = out; def inputs = in
}
case class GroupBlock(n: String, blocks: List[Block], in: List[Input], 
                      out: List[Out]) extends Block(n, in, out)
case class StandardBlock(n: String, in: List[Input], out: List[Out])
           extends Block(n, in, out)

abstract class Point(n: String){ def name = n }
case class Input(n:String) extends Point(n)

abstract class Out(n: String) extends Point(n)
case class Output(n:String) extends Out(n) 
case class Connection(connectedInput: Input, n: String) extends Out(n)

现在想象一下,我有这个没有显示的例子:

映射到这个:

val inputA = Input("sumA")
val inputB = Input("sumB")
val outputB = Output("B")

val sumAB =
    GroupBlock("GroupedSum",
      StandardBlock("Sum", List(inputA, inputB), List(outputB)) :: 
      StandardBlock("Input Provider", null, Connection(inputA, "A")::Nil ) ::
      StandardBlock("Input Provider", null, Connection(inputB, "B")::Nil ) ::         
      Nil, 
      null, 
      List(outputB))

所以...我想说:如果 2 "Integer providers""Sum" 连接,那么...

我设法通过模式匹配识别出一个“输入提供者”存在于这个:

sumAB match{
    case GroupBlock(_, 
          StandardBlock("Input Provider", null, _ :: Connection(input, _) :: _ ) :: _,
           _, _)
        => ...
    case GroupBlock(_,
          StandardBlock("Input Provider", null, Connection(input, _) :: _ ) :: _, 
          _, _)
        => ...
    //Covering 2 more cases where the order on the list matters
}

我怎么说“给我找一个StandardBlock 列表中名称为"Input Provider" 的案例”?因为这是我的主要问题之一。我需要指定所有可能的组合...现在我想做类似

case GroupBlock(_,
          StandardBlock("Input Provider", null, Connection(input, _) ::
          StandardBlock("Sum", inputList, _  ) :: _, 
          _, _)

但这意味着“给我找一个案例,其中“输入提供者”位于列表的开头,而 Sum 块位于该“Sum”之后”。我想:“给我找一个案例,其中存在一个“输入提供者”与“总和”存在于同一个列表中。

列表中的这种“查询”对于检查输入提供程序是否与找到的 Sum 块连接也很有用。我可以使用该变量 input 并询问 input 在 inputList 中的情况。

【问题讨论】:

  • 相关问题:stackoverflow.com/questions/9891638/…(是的,我知道这是你的——它可能会帮助人们了解你的目标)
  • 这就是为什么我从“按此主题的顺序”开始,并附有指向该主题的链接:)

标签: list scala pattern-matching


【解决方案1】:

您可以在匹配子句中使用守卫来提供帮助。他们是这样的:

case 模式 if 守卫 =>

其中guard 是一个表达式,它可以利用已绑定在模式中的变量。所以我认为这可能做你想做的事:

sumAB match {
  case GroupBlock(groupBlockName, blocks, _, _) if blocks.exists {
    case StandardBlock("Input Provider", _, inputProv_out) => blocks.exists { 
      case StandardBlock("Sum", sum_in, _) =>
        sum_in.exists { input =>
          inputProv_out.collect{ case Connection(connectedInput,_) =>
            connectedInput}.contains(input)
        }
      case _ =>
        false 
    }
    case _ => false
  } =>
    println("found")
  case _ =>
    println("no match")
}

这是翻译您正在编写的内容的尝试找到一个存在输入提供程序的组块,其中一个inputProv_out 输出连接到总和sum_in 输入之一

话虽如此,如果我没有犯错,我会感到惊讶。这表明您的数据结构可能不是您尝试做的最好的。或者您可能需要帮助函数来表达某些属性。

【讨论】:

  • 这是一个非常混乱的解决方案。我的例子可能是我能找到的最简单的例子之一。我应该忘记案例类并尝试使用模式匹配中的 unapply 方法吗?您能否建议对我的结构进行任何更改以简化我想要的内容?
  • @TiagoAlmeida,您的带有 Integer Provider、Sum 和 Display 的图表似乎比您的实际结构简单得多。你能像你的图表那样简化案例类吗?
  • 我没有看到解决方案。首先,我需要为每个块/输入/输出命名,以便将其展示给用户。其次,我需要知道这些联系。虽然我可以为每种类型的块做一个案例类(整数提供者是一个案例类,Sum 是一个案例类)我相信这不会是革命性的......我想简化我的结构,但我不知道我怎么能去做吧。
猜你喜欢
  • 2015-05-15
  • 2015-04-27
  • 1970-01-01
  • 1970-01-01
  • 2013-11-28
  • 2012-01-02
  • 1970-01-01
  • 2017-02-25
  • 2017-04-25
相关资源
最近更新 更多