我zipAll用于兩個大小不等的串列,如下所示:
val prices = List(5, 10, 15, 20)
val fruits = List("Guava", "Banana", "Papaya", "Apple", "Mango")
我正在使用zipAll,如下所示:
fruits zipAll (prices, "Undefined Fruit", "Price Unavailable")
產生以下結果:
List((Guava,5), (Banana,10), (Papaya,15), (Apple,20), (Mango,Price Unavailable))
我感興趣的是傳遞動態默認填充符;所以在這種情況下,我期待這樣的事情:
fruits zipAll (prices, "Undefined Fruit", s"Price Unavailable for $fruitName")
哪個應該產生:
List((Guava,5), (Banana,10), (Papaya,15), (Apple,20), (Mango,Price Unavailable for Mango))
uj5u.com熱心網友回復:
由于 stdlib 不提供此類功能,因此您需要像這樣自己實作它:
def zipAllDynamic[A, B](left: List[A], right: List[B])(leftDefault: B => A, rightDefault: A => B): List[(A, B)] =
left
.map(l => Option(l))
.zipAll(right.map(r => Option(r)), None, None)
.collect {
case (Some(l), Some(r)) => (l, r)
case (Some(l), None) => (l, rightDefault(l))
case (None, Some(r)) => (leftDefault(r), r)
}
雖然,這是非常昂貴的。
您可以使用尾遞回函式來提高操作的效率;或者你可以使用lazynes的魔法:
def zipAllDynamic[A, B](left: List[A], right: List[B])(leftDefault: B => A, rightDefault: A => B): List[(A, B)] =
left
.iterator.map(l => Option(l))
.zipAll(right.iterator.map(r => Option(r)), None, None)
.collect {
case (Some(l), Some(r)) => (l, r)
case (Some(l), None) => (l, rightDefault(l))
case (None, Some(r)) => (leftDefault(r), r)
}.toList
然后你可以像這樣使用它:
val prices = List(5, 10, 15, 20)
val fruits = List("Guava", "Banana", "Papaya", "Apple", "Mango")
val result = zipAllDynamic(fruits, prices.map(_.toString))(_ => "Undefined Fruit", fruitName => s"Price Unavailable for ${fruitName}")
// result: List[(String, String)] = List((Guava,5), (Banana,10), (Papaya,15), (Apple,20), (Mango,Price Unavailable for Mango))
注意:記住Scala是一種靜態和強型別語言,因為這種混合
Int和你String想要的會導致List[(String, Any)]你永遠不想要的,而是我將所有價格轉換Strings為 zip 之前的價格。
(如何將此輔助函式轉換為擴展方法,留給讀者作為練習)
您可以在此處看到運行的代碼。
PS:如果您使用貓,您可以使用align和map更好地控制一切。
import cats.data.Ior
import cats.syntax.all._
val result = (prices align fruits).map {
case Ior.Both(price, fruit) => s"${fruit} price is: ${price}"
case Ior.Right(fruit) => s"Price Unavailable for ${fruit}"
case Ior.Left(_) => "Undefined Fruit"
}
// result: List[String] = List("Guava price is: 5", "Banana price is: 10", "Papaya price is: 15", "Apple price is: 20", "Price Unavailable for Mango")
感謝 Jasper 指出我們可以將前面的align map與以下內容結合起來:
val result = prices.alignWith(fruits) {
case Ior.Both(price, fruit) => s"${fruit} price is: ${price}"
case Ior.Right(fruit) => s"Price Unavailable for ${fruit}"
case Ior.Left(_) => "Undefined Fruit"
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/372695.html
標籤:斯卡拉
