1

好的,我必须在这里与一些愚蠢的事情作斗争(Scala 的新手),在这种情况下,如果它是微不足道的,请道歉。

我有一个类Action,它带有一个名称(与问题无关)和一个列表参数。

每个参数都有一组可能的值,我想为Action. 我一直在尝试使用 afor-comprehension但不是填写所有参数,而是只替换了一个值的组合。

我的代码看起来像这样(我简化它只是为了说明问题):

case class ParamType(name: String)
{
  def matchesType(that: ParamType): Boolean = 
      this.name == that.name
}

sealed abstract class Param (paramType : ParamType)

case class VarParam(parameter : String, paramType : ParamType) extends Param (paramType)

case class ValueArg(name : String, paramType : ParamType) extends Param(paramType)


case class Action(name: String, params: List[Param])
{
   def possibleActions(possibleValues : Set[ValueArg]) : Set[Action] = 
     for {
   parameter <- params.collect({case pt: VarParam => pt})
   argument <- possibleValues
   if (argument.matchesType(parameter))
   } yield replaceParam(parameter, argument)

   def replaceParam(parameter: VarParam, argument: ValueArg) : Action =
   {
     val i = parameters.indexOf(parameter)
     if (i >= 0)
       Action(name, parameters.updated(i, argument)
   }      
}




   object tester {

    def main(args: Array[String]) {
       val possibleValues = Set[ValueArg](new ValueArg("a1", new ParamType("Atype")), 
                                       new ValueArg("a2", new ParamType("Atype")),
                                       new ValueArg("a3", new ParamType("Atype")),
                                       new ValueArg("b1", new ParamType("Btype")),
                                       new ValueArg("b2", new ParamType("Btype")),
                                       new ValueArg("b3", new ParamType("Btype")),
                                       new ValueArg("c1", new ParamType("Ctype")),
                                       new ValueArg("c2", new ParamType("Ctype")),
                                       new ValueArg("c3", new ParamType("Ctype")))

    val action1 = new Action("action1", List[Param](new VarParam("A", new ParamType("Atype")), new VarParam("B", new ParamType("Btype")), new VarParam("C", new ParamType("Ctype"))))

    val possibleActions = action1.possibleActions(possibleValues)

    println(possibleActions)

    }
   }

该函数replaceParam只返回一个参数替换为参数的操作。

因此,如果我有带有参数 A、B、C 的 action1,每个参数都可以采用 {a1、a2、a3}、{b1、b2、b3} 和 {c1、c2、c3} (假设它们属于同一类型) ,我最终得到:

action1(a1, B, C) , action1(A, b1, C), action1(A, B, c1), action1(a2, B, C) 等。

但我想要的是:

动作1(a1,b1,c1),动作1(a1,b1,c2),动作1(a2,b1,c1)等。

实现这一目标的最优雅的方法是什么?

4

1 回答 1

1

以下是您的问题的简单递归解决方案。但是,请注意,将可能的值作为 a 传递可能Set会出现问题,因为这样可能的值没有顺序,因此所有(而不仅仅是一个特定的)对应参数将迭代所有具有合适参数类型的值。现在这应该按照您的要求进行:

case class ParamType(name: String) {
  def matchesType(that: ParamType): Boolean =
    this.name == that.name
}

sealed abstract class Param(val paramType: ParamType)
case class VarParam(parameter: String, override val paramType: ParamType) extends Param(paramType)
case class ValueArg(name: String, override val paramType: ParamType) extends Param(paramType)

case class Action(name: String, params: List[Param]) {
  lazy val varParams: List[Param] =
    params collect {
      case pt: VarParam => pt
    }

  def possibleActions(possibleValues: Set[ValueArg]): Set[Action] = {
    val pvs  = possibleValues groupBy (_.paramType)
    def aux(acc: List[Param], rem: List[Param]): Set[Action] = rem match {
      case Nil => Set(Action(name, acc.reverse))
      case x :: xs => for {
        pv <- pvs(x.paramType) if pvs.contains(x.paramType)
        rest <- aux(pv :: acc, xs)
      } yield rest
    }
    aux(Nil, varParams)
  }
}

val possibleValues = Set(
  ValueArg("a1", ParamType("Atype")),
  ValueArg("a2", ParamType("Atype")),
  ValueArg("a3", ParamType("Atype")),
  ValueArg("b1", ParamType("Btype")),
  ValueArg("b2", ParamType("Btype")),
  ValueArg("b3", ParamType("Btype")),
  ValueArg("c1", ParamType("Ctype")),
  ValueArg("c2", ParamType("Ctype")),
  ValueArg("c3", ParamType("Ctype")))

val action1 = Action("action1",
  List(VarParam("A", ParamType("Atype")),
    VarParam("B", ParamType("Btype")),
    VarParam("C", ParamType("Ctype"))))

val possibleActions = action1.possibleActions(possibleValues)
assert(possibleActions.size == 3 * 3 * 3)
于 2013-11-19T06:28:32.117 回答