我目前有一個結果值,它是一個字串,表示圖中的回圈
> scala result
String =
0:0->52->22;
5:5->70->77;
8:8->66->24;8->42->32;
. //
. // trimmed to get by point across
. //
71:71->40->45;
77:77->34->28;77->5->70;
84:84->22->29
但是,我希望輸出包含介于兩者之間的數字,并且最多包含某個值。示例代碼的值 = 90
0:0->52->22;
1:
2:
3:
4:
5:5->70->77;
6:
7:
8:8->66->24;8->42->32;
. //
. // trimmed
. //
83:
84:84->22->29;
85:
86:
87:
88:
89:
90:
如果它有幫助或有任何不同,則將此值更改為串列以供以后使用,例如
list_result = result.split("\n").toList
List[String] = List(0:0->52->22;, 5:5->70->77;, 8:8->66->24;8->42->32;, 11:11->26->66;11->17->66;
我最初的想法是將缺失的數字插入串列中,然后對其進行排序,但我在排序時遇到了麻煩,所以我轉而在這里尋找更好的方法。
uj5u.com熱心網友回復:
將您的list_result變成Map具有默認值的。然后遍歷所需的數字范圍,將每個范圍交換為其Map值。
val map_result: Map[String,List[String]] =
list_result.groupBy("\\d :".r.findFirstIn(_).getOrElse("bad"))
.withDefault(List(_))
val full_result: String =
(0 to 90).flatMap(n => map_result(s"$n:")).mkString("\n")
這是一個Scastie 會話,可以查看它的運行情況。
uj5u.com熱心網友回復:
一種選擇是使用 aMap作為中間資料結構:
val l: List[String] = List("0:0->52->22;", "5:5->70->77;", "8:8->66->24;8->42->32;", "11:11->26->66;11->17->66;")
val byKey: List[Array[String]] = l.map(_.split(":"))
val stop = 90
val mapOfValues = (1 to stop).map(_->"").toMap
val output = byKey.foldLeft(mapOfValues)((acc, nxt) => acc (nxt.head.toInt -> nxt.tail.head))
output.toList.sorted.map {case (key, value) => println(s"$key, $value")}
這將為您提供所需的輸出。它將您的輸入字串分解為偽鍵值對,創建一個映射來保存結果,將 的元素byKey插入映射中,然后回傳結果的排序串列。
注意:如果您在生產代碼之類的任何內容中使用它,您需要正確檢查每個ArrayinbyKey確實有兩個元素,以防止nullPointerExceptions以后呼叫headand tail.head。
uj5u.com熱心網友回復:
提供的解決方案很好,但我想建議一種可以懶惰地處理資料并且不需要一次將所有資料保存在記憶體中的解決方案。
它使用了一個叫做 的好函式unfold,它允許從一個開始狀態“展開”一個集合,直到你認為集合結束的點(docs)。
它并不完美,但我希望它可以幫助:
def readLines(s: String): Iterator[String] =
util.Using.resource(io.Source.fromString(s))(_.getLines)
def emptyLines(from: Int, until: Int): Iterator[(String)] =
Iterator.range(from, until).map(n => s"$n:")
def indexOf(line: String): Int =
Integer.parseInt(line.substring(0, line.indexOf(':')))
def withDefaults(from: Int, to: Int, it: Iterator[String]): Iterator[String] = {
Iterator.unfold((from, it)) { case (n, lines) =>
if (lines.hasNext) {
val next = lines.next()
val i = indexOf(next)
Some((emptyLines(n, i) Iterator.single(next), (i 1, lines)))
} else if (n < to) {
Some((emptyLines(n, to 1), (to, lines)))
} else {
None
}
}.flatten
}
您可以在 Scastie 上看到這一點。
什么unfold是從一個狀態(在這種情況下,行號from和帶有行的迭代器)和每次迭代開始:
- 如果迭代器中仍有元素,則獲取下一項,標識其索引并回傳:
- 作為下一項
Iterator,空行直到最新的行號,后跟實際行- 例如,當達到 5 時,將發出 1 和 4 之間的空行,以 5 開頭的行終止
- 作為下一個狀態,發出的專案中最后一個之后的行的索引和迭代器本身(它是有狀態的,
unfold在每次迭代時被重復呼叫消耗)- 例如在處理 5 之后,下一個狀態是 6 并且迭代器
- 作為下一項
- 如果迭代器中不再有元素但
to尚未到達索引,則它會發出另一個Iterator要列印的剩余專案(在您的示例中,84 之后的專案) - 如果兩個條件都為假,我們就不再需要發出任何東西,我們可以關閉“展開”集合,通過回傳 a
None而不是Some[(Item, State)]
這將回傳一個Iterator[Iterator[String]]其中每個嵌套迭代器都是從一行到下一行的值范圍,默認的空行“夾在”中間。呼叫flatten將其轉換為所需的結果。
我使用 anIterator來確保在任何時候并且僅在實際使用時僅將基本狀態保存在記憶體中。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/352644.html
標籤:斯卡拉
上一篇:Scala:強制某些函式的型別在特征中使用this的型別
下一篇:如何修復與控制器相關的錯誤?
