18

同じアリティの2つのタプルがある場合、辞書式順序でそれらを比較するにはどうすればよいですか?これは次のスニペットのように単純なはずですが、そうではありません。それを行う方法の簡単な例はありますか?

var x = (1,2,3) < (1,2,4)

それらがリストである場合、違いまたはリストの終わりが見つかるまでリストのヘッドを比較する再帰関数を定義できますが、タプルに対してはそれができないと思います。

4

3 に答える 3

27

簡単ではありませんが

var x = (1,2,3) < (1,2)

とてもシンプルに見えます、

var x = (1,false,3) < (1,2)

ではありません。順序付けされていないタイプをどのように処理しますか?同じタプル位置で異なるタイプをどのように処理しますか?

すべてのタイプを同じにするように義務付けていますか?その場合、タプルはありません。タプルの要点は、そのアリティが固定されており(静的にその大きさを知っている)、各要素が異なるタイプである可能性があることです。

その問題に気付いた場合(そしてそうしないように一生懸命努力したい場合)、Shapelessを取得し、タプルをHListのようなものに変換してから、それを比較してみます。

編集

ああ、今でははるかに簡単です:

import scala.math.Ordering.Implicits._
var x = (1,2,3) < (1,2,4)

これらの追加の暗黙は、状況によっては暗黙の発散を引き起こす可能性があるため、自動的には使用できません。

于 2012-06-19T15:41:37.213 に答える
14

Danielのソリューションは、使用したい場合は機能しますが、メソッド<が必要な場合compareは、次のように実行できます(たとえば)。

implicitly[Ordering[Tuple2[Int, Int]]].compare((1,2), (2,3))

同等のパーツを持つすべてのタプルに対して定義された順序があります。

于 2012-09-05T22:03:54.443 に答える
2

最も簡単な方法は、それらに暗黙のOrdering [T]を定義することですが、この順序をsort関数(またはそれらを比較したい他の関数)に渡す必要があります。暗黙的に渡すことも可能です。

別の方法は、暗黙のキャストを介して<演算子によってタプルクラスを拡張することです。

implicit def compareTuple[T](lhs: (T,T)) = new {
   def <(rhs: (T,T)) = lhs._1<rhs._1 || (lhs._1==rhs._1 && lhs._2<rhs._2)
}

編集: 他の比較演算子も必要な場合は、Ordered[T]から継承して取得できます。

implicit def compareTuple[T](lhs: (T,T)) = new Ordered[(T,T)] {
   def compare(rhs: (T,T)) = ...
}

edit2: 異なるサイズのタプルも比較する必要がある場合は、すべてのタプルクラスで定義されているproductIterator関数を使用でき(ドキュメントを参照)、タプルに対してイテレータを取得できます。このようにして、リストで行うのと同じように関数を書くことができます。

edit3: これは次のようになります:

implicit def compareTuple[T <: Product](lhs: T) = new Ordered[T] {
    def compare[U <: Product](rhs: U) = {
        def compare(lhs: Any, rhs: Any) = ...
        def iteratorCompare(lhs: Iterator[Any], rhs: Iterator[Any]):Int = 
            if(!lhs.hasNext)
                if(!rhs.hasNext)
                    0
                else
                    -1
            else if(!rhs.hasNext)
                1
            else
                compare(lhs.next,rhs.next)
        iteratorCompare(lhs.productIterator,rhs.productIterator)
    }
}

しかし、このアプローチでは、タイプに注意する必要があります。関数はタプル要素のタイプを認識しないため(同じタプル内で異なる場合があります)、Iterator[Any]のみを提供できます。したがって、必要なものを処理するには、compare(Any、Any)関数を定義する必要があります。

于 2012-06-19T13:54:09.870 に答える