2015-08-08 79 views
2

我不確定這是否可能,但是我想根據一些依賴於流輸出的條件對流進行分區。用我認爲的一個例子來說是有道理的。流的分區

我將創建一串訂單,由於實際使用案例是進入訂單流,因此不知道下一個訂單是什麼,甚至是訂單的完整列表:

scala> case class Order(item : String, qty : Int, price : Double) 
defined class Order 

scala> val orders = List(Order("bike", 1, 23.34), Order("book", 3, 2.34), Order("lamp", 1, 9.44), Order("bike", 1, 23.34)) 
orders: List[Order] = List(Order(bike,1,23.34), Order(book,3,2.34), Order(lamp,1,9.44), Order(bike,1,23.34)) 

現在我想將這些訂單分區/分組到一個包含重複訂單的集合和另一個包含唯一訂單的集合。所以在上面的例子中,當我強制流時,它應該創建兩個流:一個用於一個腳踏車的兩個訂單(因爲它們是相同的),另一個流包含所有其他訂單。

我試過如下:

創建的分區功能:

scala> def matchOrders(o : Order, s : Stream[Order]) = s.contains(o) 
matchOrders: (o: Order, s: Stream[Order])Boolean 

然後試圖將其應用到流:

scala> val s : (Stream[Order], Stream[Order]) = orders.toStream.partition(matchOrders(_, s._1)) 

我得到一個空指針異常,因爲我猜s._1最初是空的?我不確定。我嘗試了其他方法,但我並沒有走得太遠。有沒有辦法實現這種分區?

回答

2

不管怎麼說,因爲第一個重複的Order在處理其重複時已經到了唯一的Stream

最好的方法是創建一個Map[Order, Boolean],它告訴您Order是否在原始訂單列表中多次出現。

val matchOrders = orders.groupBy(identity).mapValues(_.size > 1) 
val s : (Stream[Order], Stream[Order]) = orders.toStream.partition(matchOrders(_)) 
+0

正如我所解釋的,事先並不知道整個訂單列表是什麼,所以你不能像你那樣編寫你的matchOrders謂詞。我創建了上面的訂單列表來舉例說明。但是你對第一個訂單確實有一個很好的觀點。我也考慮過這個問題。我想我可能需要創建某種遞歸流結構;目前我正在對此進行試驗 –

1

請注意,您只能知道訂單在流完成後沒有重複項。因此,由於標準的Stream構造函數要求您知道流是否爲空,因此它看起來不夠懶惰:您必須強制原始流甚至開始構建無重複流。當然,如果你這樣做,Helder Pereira的答案也適用。