2016-11-03 74 views
1

我有一個整數列表:模式匹配用條件列表

val l = List(100, 200, 100) 

我試圖模式匹配它的價值,但是規則有點複雜。

1. 100 or 200, but at least 1 100 
2. 300 or 400, with at least 1 300 and the rest 300 or 400 
3. 700 or 800, with at least 1 700 and the rest 700 or 800 

是否可以在模式匹配表達式中表達它?

val result: Option[String] = l match { 
case (100 | 200) ??? => "1" 
case (300 | 400) ??? => "2" 
case (700 | 800) ??? => "3" 
case _ => None 
} 
+0

值不匹配會發生什麼情況?像'List(200,200)'(即不包含'100')? – maasg

+1

並且在一個分支中返回「1」而在另一個分支中沒有返回沒有意義。 – pedrofurla

回答

1

爲了避免對每個案例O(n^2)進行詳盡的檢查,首先將列表O(n)的最小元素區分大小寫,並驗證該列表僅包含預期元素(O(n))。這應該工作:

val result:Option[Int] = (l.min, l) match { 
    case (100, l) if l.forall(Set(100,200)) => Some(1) 
    case (300, l) if l.forall(Set(300,400)) => Some(2) 
    case (700, l) if l.forall(Set(700,800)) => Some(3) 
    case _ => None 
} 
0

你不能真正匹配這樣的值。你可以這樣做:

l match { 
    case _ if l.forall(Set(100,200).contains) && l.contains(100) => Some("1") 
    case _ if l.forall(Set(300,400).contains) && l.contains(300) => Some("2") 
    case _ if l.forall(Set(700,800).contains) && l.contains(700) => Some("3") 
    case _ => None 
} 

不是最有效的,因爲你遍歷每個案例的列表兩次。它可以通過某種形式的foldLeft更高效地完成。

1

這是你正在尋找的邏輯?根據你的描述有點難以分辨。

val result: Option[String] = lst match { 
    case 100 :: _ => Some("1") 
    case 200 :: t if t contains 100 => Some("1") 

    case 300 :: _ if lst.forall(x => x==300 || x==400) 
      => Some("2") 
    case 400 :: t if lst.contains(300) && lst.forall(x => x==300 || x==400) 
      => Some("2") 
    case 700 :: _ if lst.forall(x => x==700 || x==800) 
      => Some("3") 
    case 800 :: t if lst.contains(700) && lst.forall(x => x==700 || x==800) 
      => Some("3") 
    case _ => None 
}