2017-08-23 95 views
4

我想寫一個排序函數,它可以處理任何序列並返回傳遞給該函數的相同序列。所以,我想出了這個解決方案:scala通用排序函數不能與數組一起工作

def qckSrt[U: Ordering, C <: Seq[U]](xs: C with SeqLike[U, C]) 
    (implicit bf: CanBuildFrom[C, U, C]): C = { 
    val n = xs.length 
    val b = bf() 

    if (n <= 1) xs 
    else { 
    val p = xs.head 
    val (left, right) = xs.tail partition { 
     implicitly[Ordering[U]].lteq(_, p) 
    } 
    b ++= qckSrt(left) 
    b += p 
    b ++= qckSrt(right) 
    b.result() 
    } 
} 

所以它的工作原理與列表,向量,arraybuffers ...但它無法與普通陣列的工作:

scala> qckSrt(Array(1, 2, 6, 2, 5)) 
<console>:16: error: inferred type arguments [Int,Any] do not conform to method qckSrt's type parameter bounds [U,C <: Seq[U]] 
     qckSrt(Array(1, 2, 6, 2, 5)) 
     ^
<console>:16: error: type mismatch; 
    found : scala.collection.mutable.ArrayOps.ofInt 
    required: C with scala.collection.SeqLike[U,C] 
     qckSrt(Array(1, 2, 6, 2, 5)) 
      ^
<console>:16: error: No implicit Ordering defined for U. 
     qckSrt(Array(1, 2, 6, 2, 5)) 

有沒有辦法讓這個爲陣列工作嗎?

+0

爲什麼要這樣做? SeqLike已經有很多排序方法了。 –

+0

只供學習 –

回答

2

您可以用隱式轉換替換繼承。對於數組,這將使用隱式包裝轉換和對於已經SeqLike類型,它將使用一個子類型的證據(implicitly[C[U] <:< SeqLike[U, C[U]]]):

import scala.collection._ 
import scala.collection.generic.CanBuildFrom 


def qckSrt[U: Ordering, C[_]](xs: C[U])(implicit 
    bf: CanBuildFrom[C[U], U, C[U]], 
    asSeq: C[U] => SeqLike[U, C[U]] 
): C[U] = { 
    val n = xs.length 
    val b = bf() 

    if (n <= 1) xs 
    else { 
    val p = xs.head 
    val (left, right) = xs.tail partition { 
     implicitly[Ordering[U]].lteq(_, p) 
    } 
    b ++= qckSrt(left) 
    b += p 
    b ++= qckSrt(right) 
    b.result() 
    } 
} 

添加一個「洞」,以一個型C需要U是在呼叫現場適當推斷。

相關問題