質問: Seq("あ", "お", "え", "い", "う", "か") ``` 処理方法としましては、 1.データを取得(A) A ... リスト B ... 並び替え対象リスト 2.リスト(A)を分割 分割条件: リスト(A)のデータが、並び替え対象リスト(B)の"挿入する値"と一致、かつ、ターゲットとなる値が、がリスト(A)に含まれている A` ... 条件が一致せず残ったリスト C ... 条件の一致したリスト 3.条件が一致せず残ったデータ(A`)を、forなどで1件づつ処理を行い、並び替え対象のデータと一致した場合、Cのリストからデータを取得し、A`に挿入 と考えておりました。 プログラムを組んでうちに、3の段階時点で、"お"のつぎが"え"とならないのではないかと疑問に思い、今回、質問内容をやりたいことのみを記載し質問してしまいました。 難しく考え過ぎているのかもしれませんが、ご教授いただけると幸いです。 お手数をおかけしますが、よろしくお願い致します。
回答: 回答ではないのですが・・・ ご質問にはやりたいことの例しか述べられておらず「仕様」が述べられていません。いうまでもなく、仕様によってどのようなアルゴリズムを採るべきかは変化します。もし質問者さんが想定している仕様を明示せずその想定と違う前提を置いたアルゴリズムを回答者が回答してしまうと 「いえそういう仕様ではないのです」 といわないといけなくなりますね。ソフトウェアを設計する際に「利用者が正確な要件を言わない」といったことはよくあること(w;)と思いますが、そうした場合「正確な要件を確認する」ところから始めるべきであろうと思います。 例から想像すると以下のような規則であるように思えますが、このような前提をお考えなのかどうか確認したく思いました。 * 結果の末尾がShima(α,β)であるとき、a,bの残り要素にShima(?,α)はたかだか一つしかない * 結果の末尾がShima(α,β)であるとき、a,bの残り要素にShima(?,α)がなければa,bの残り要素の先頭を次の要素とする * 結果の最初の要素はa,bの残り要素の中の先頭要素とする (最初の回答に書いた規則は曖昧だったので訂正しました。失礼しました。) 追記:補足された質問内容に従い考えてみました。結論からいうと最初のご質問にあるようなa, bのリストのうちaのみ用いる方法です。ちょっと分かりにくい論理にも見えるのでもっと明解な方法があるかも知れません。 ``` object Reorder { case class Order(val next: String, val prev: String) def main(args: Array[String]): Unit = { // 並び替え対象リスト val list = Seq("あ", "い", "う", "え", "お", "か") // 順序制約リスト val order = Seq(Order("お","あ"), Order("え","お")) // 順序マップを作る(previous -> nextのペア) val orderMap = order.map(o ⇒ o.prev → o.next).toMap // 与えた引数から順序マップによって決まる固定的な順列を返す // マップ内に含まれない場合は単に引数を単一要素とする列を返す // (本件の場合"あ"を渡すとSeq("あ", "お", "え")が返ります。 def makeOrderedSeq(s: String): Seq[String] = orderMap.get(s) match { case Some(next) ⇒ s +: makeOrderedSeq(next) case None ⇒ Seq(s) } // 順序マップ(のnext)に出現しないもののみの列へ要素を挿入 val result = list .filter(s ⇒ order.forall(_.next != s)) .flatMap(makeOrderedSeq(_)) println(s"result = ${result}") } } ``` 上はあまり処理効率を気にしておらず順序制約のリストの長さが10個やそこらの程度ならよいのですが、それ以上の長さだとmakeOrderedSeqが再帰になっているので危険かも知れません。 再帰を使わないと以下のような不格好なものになってしまいます・・・ Scala使いの方には「ひどいコード」と言われてしまいそうですが orz ``` def makeOrderedSeq(s: String): Seq[String] = orderMap.get(s) match { case Some(next) ⇒ val b = mutable.Buffer(s) var n = next do { b += n n = orderMap.getOrElse(n, null) } while (n != null) b case None ⇒ Seq(s) } ``` もっとよい回答があると思いますが自分の程度ではこのくらいの回答が関の山です。