2016-11-10 38 views
0

我有一個Map[Int, Set[Int]]並給定了一個項目,我想返回索引到Set where項目所在的鍵。例如,如果我有一個Map(1 -> Set("a"), 2 -> Set("b"), 3 -> Set("c","z"))。假設該項目是"z"我想返回3,因爲3是索引到包含3的集合的關鍵字。 這是我目前擁有的,但我似乎無法找到獲得鑰匙的好方法。我只能得到這個值,Set[Int]。假設該項目將只在一個可能的集合中。如果你需要返回一個或None然後Option[]將要走的路Scala:如何返回包含項值的項的值,其值是Set?

def find[A, B](m: Map[A, Set[B]], item: B): Option[A] = 
    m.find { case (key, set) => set.contains(item) } 
    .map { case (key, set) => key } 
+0

你這是什麼想要返回項目是否在多個鍵下? – jwvh

+0

你的意思是設置(「c」,「z」),還是它真的是一個字符串? – soote

+0

@jwvh假設該項目將只在一個可能的集合中,否則就沒有。我加入了這個問題。 –

回答

2

collectFirst爲這個做:

val m = Map(1 -> Set("a"), 2 -> Set("b"), 3 -> Set("c","z")) 

m.collectFirst{case (k,v) if v.contains("z") => k} 
//> res0: Option[Int] = Some(3) 

,我總是忘記Set可以作爲一個函數本身(即apply相同contains

m.collectFirst{case (k,v) if v("z") => k} 
//> res0: Option[Int] = Some(3) 
+0

這是很整潔的!在效率方面,這是最好的嗎? –

+0

它遍歷列表一次,因此它更有效率的查找/地圖,可能與平面圖大致相同。但除非你真的需要微觀優化,我認爲清晰更重要 –

+0

「效率」取決於如果你要做很多這些查找,然後建立一個反向地圖, –

2

這一發現運營商可以很好地工作在這裏。如果需要返回一個,多個或不需要,則可以返回List[]

val m = Map(1 -> Set("a"), 2 -> Set("b"), 3 -> Set("c","z")) 

m.flatMap{ case (k,vs) => if (vs.contains("z")) Seq(k) else Seq() } // List(3) 
m.flatMap{ case (k,vs) => if (vs.contains("w")) Seq(k) else Seq() } // List() 
+0

'.map(_._ 1' for? –

+0

獲取第一個值在這種情況下,它只是返回鍵 – soote

2

def find(djs: Map[Int, Set[Int]], item: Int) :Int = { 
for ((key, set) <- djs) { 
    if (set.contains(item)) { 
    key 
    } 
} 
+1

過濾器是這個任務更具描述性的hof,no?'m.filter(_._ 2.contains(「z」))。map(_._ 1) ' – soote

+0

@soote,good point。我同意 – jwvh

相關問題