[英]Filter a Scala Seq[(String, String)] using a Seq[String]
我有這個Seq[(String, String)]
:
val tupleSeq: Seq[(String, String)] = Seq(
("aaa", "A_A_A"),
("bbb", "B_B_B"),
("ccc", "C_C_C")
)
我想在tupleSeq
上使用給定的seqA
:
val seqA: Seq[String] = Seq("aaa", "bbb")
為了得到:
val seqB: Seq[String] = Seq("A_A_A", "B_B_B")
有任何想法嗎?
一種方法是使用未更改的數據。
// The size of `data` is M
// The size of `query` is N
val data: Seq[(String, String)] = Seq(
("aaa", "A_A_A"),
("bbb", "B_B_B"),
("ccc", "C_C_C")
)
val query: Seq[String] = Seq("aaa", "bbb")
// Use the data as is
// O(M * N)
for {
(key, value) <- data
lookup <- query
if key == lookup
} yield value
這種方法的問題是總體復雜度為O(M * N)
,其中M
和N
是data
和query
collections 的大小。 如果已知M
或N
非常小,並且可以通過使用可以提前終止的函數(如find
,在另一個答案中舉例說明)在實際中進一步改進,這可能是完全可以接受的。
如果M
和N
相當大,您可能需要花費必要的時間將它們轉換為適當的數據結構(這會以與集合大小成線性關系的方式消耗時間和空間)。
根據您希望更大的大小,您可能希望將數據轉換為 map 並查找相關鍵,或者將查詢轉換為集合並迭代 map 中的每個鍵以查找相關鍵。
我希望在大多數情況下查詢的數據大於查詢,因此您可能希望將數據轉換為 map。 保留 map 還可以讓您多次查詢它,而不會花時間將其變成更合適的查詢結構。
// Turn the query into a set and iterate the data
// O(M)
val lookups = query.toSet
data.collect {
case (key, value) if lookups.contains(key) => value
}
// Turn the data into a map and iterate the query
// O(N)
val map = data.toMap
query.collect(map)
您可以在 Scastie 上使用此代碼。
val tupleSeq: Seq[(String, String)] = Seq( ("aaa", "A_A_A"), ("bbb", "B_B_B"), ("ccc", "C_C_C") ) val seqA: Seq[String] = Seq("aaa", "bbb") // List(A_A_A, B_B_B) val seqB = for { key <- seqA value <- tupleSeq.find(_._1 == key).map(_._2) } yield value
你的tupleSeq
自然看起來像一個鍵值對的Map
,所以你應該把它當作一個。 通過以下觀察,代碼變得非常簡單:
val myMap = tupleSeq.toMap
val seqB = seqA.collect(myMap) // List(A_A_A, B_B_B)
對於額外的空間復雜度,您的查詢會獲得 O(1) 的分攤時間復雜度,這對您的用例來說很好。
請注意使用collect
而不是map
因為它會丟棄在Map
中沒有映射值的鍵。
你可以嘗試這樣的事情:
val seqB = tupleSeq.filter{x => seqA.contains(x._1)}.map(x => x._2)
它過濾序列並保留第一個值是第二個序列的一部分的元組,然后將元組映射到第二個值。
seqB.foreach(println)
然后輸出:
A_A_A
B_B_B
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.