4

マップがあるとします:

val m = Map("foo" -> 10, "bar" -> 5)

これを次の形式の文字列に変換したい (キーと値は「:」で区切られ、異なる要素は「,」で区切られている):

"bar:5,foo:10"

キーが順序付けされていることに注意してください。

この変換を一般的に実行する関数を作成するにはどうすればよいですか? 私は試した

def f[A, B](m: Map[A, B]): String = {
  m.toList.sortBy(_._1).map { x => x._1 + ":" + x._2 }.mkString(",")
}

しかし、これは機能しません。どういうわけか、A注文可能であることを指定する必要があるからです。これを行う方法がわかりません-関数に暗黙的Ordererなパラメーターを追加しようとしましたが、機能しませんでした。

4

1 に答える 1

8

タイプクラスを使用しOrderingます。

def f[A: Ordering, B](m: Map[A, B]): String = {
  m.toList.sortBy(_._1).map { x => x._1 + ":" + x._2 }.mkString(",")
}

fこれにより、暗黙のパラメータを使用して別のパラメータリストが追加されOrderingます。メソッドシグネチャは、実際には舞台裏でこれに変換されます。

def f[A, B](m: Map[A, B])(implicit evidence: Ordering[A]): String

次に、evidenceパラメータが取得されsortBy、要素の比較に使用されます。

編集:

Orderedと同じように使用することはできませんのでご注意くださいOrderingOrderedトレイトは、(Javaのように)ソートされるオブジェクトタイプそのものと混合されることを意図しています。言い換えれば、A拡張するOrdered[A]必要があり、それからあなたはそれをとして書くでしょうA <: Ordered[A]

ただし、この継承アプローチは、柔軟性が低いためOrdered、タイプクラスアプローチよりも強力でOrderingはありません。他の誰かが定義Aし、それを拡張することを決定しなかった場合、 (少なくともラッパークラスを作成せずに)Ordered[A]それを使用することはできません。sortBy一方、継承Ordering[A]するものを変更せずに、スコープ内で新しい暗黙をいつでも宣言し、これを任意の方法で実装できます。これにより、の実装者がそうするのを忘れたときにタイプのオブジェクトがどのように順序付けられるかを定義することと、デフォルト以外の順序付けが必要なときにそれらがどのように順序付けられるかを再定義することができます。AOrderingAA

于 2012-06-19T07:58:01.677 に答える