1

OK、私はここで愚かなこと (Scala の新機能) に苦労しているに違いありません。

Action名前(問題とは関係ありません)とリストパラメータを取るクラスがあります。

各パラメーターには可能な値のセットがあり、のパラメーターに対して可能な引数の完全なリストを生成したいと考えていますAction。私は a を使用しようとしましたfor-comprehensionが、すべての引数を入力するのではなく、1 つの値だけを置き換えた組み合わせを取得しています。

私のコードは次のようになります (問題を説明するために単純化しました):

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) など

しかし、私が欲しいのは:

action1(a1, b1, c1), action1(a1, b1, c2), action1(a2, b1, c1) など

これを達成するための最もエレガントな方法は何ですか?

4

1 に答える 1

1

以下は、問題に対する単純な再帰的な解決策です。ただし、可能な値を として渡すと、Set問題が発生する可能性があることに注意してください。この方法では、可能な値に順序がなく、対応するすべての (特に 1 つだけでなく) パラメーターが、適切なパラメーターの型を持つすべての値を反復処理するためです。今、これはあなたが尋ねたことをするはずです:

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 に答える