2013-04-17 29 views
14

有沒有一種方式來指定一個模式匹配一​​個大小大於(或小於)或等於Scala中的某個值的列表?模式匹配的特定大小或更大/更小的列表

例如,如果我想同樣的動作適用於大小爲3或更低的全部名單:

list match { 
    case Nil => op(list) 
    case x :: Nil => op(list) 
    case x :: y :: Nil => op(list) 
    case x :: y :: z :: Nil => op(list) 
    case x :: tail => other(list) 
} 

有沒有減少這兩種情況下呢?

+0

我認爲它可以用一個後衛來完成... ...的情況下,如果(tail.size> = X)=> – Dan

回答

11

是的,雖然你需要扭轉的情況下,順序:

list match { 
    case l @ (_ :: _ :: _ :: _) => other(l) 
    case l => op(l) 
} 

請注意,我已經綁定一個新的變量l在模式,而不是指list的列表,以及當我不需要變量時,我使用了_。我建議堅持這兩種做法,但如果沒有這些做法,答案將完全一樣。

+1

我沒有看到使用這種混淆的語法點時的保護條件這個工作是否在問題中提出。 –

+1

@ DenisR:首先,我回答了問題的提問,其次,我不確定這個答案實際上比守衛條件更不習慣,因爲當你使用列表時,'長度'是一個昂貴的操作。如果你想避免遍歷列表(你應該),你必須寫'case l if l.lengthCompare(3)> -1',這是它自己的一種尷尬。 –

+1

你是對的複雜性和使用lengthCompare。 我更喜歡這個解決方案,因爲長度是明確寫入的,而不是寫成一些「_」-1。 感謝您的解釋。 –

6

簡單的舊的if/else?有什麼問題?

list.splitAt(len) match { 
    case (xs, Nil) => other(xs) 
    case (_, _) => op(list) 
} 

而且其複雜性O(len)因此即使列表中,如果長,len是決定性的因素:

if (list.length >= minimumLength) 
    longer(list) 
else 
    shorter(list) 
+1

如果列表真的很長,該怎麼辦?沒有使用長度的匹配/情況會更好... – huynhjl

+5

好點。在這種情況下,你可以使用'lengthCompare'。 –

+0

我不確定「真的很長」可能是什麼,但是'Lists'每個元素都有相當大的開銷,並且對於非常大的集合沒有強烈的指示。他們真的只有一個優點:非常有效的頭部/尾部分解。 –

4

您也可以做到這一點。

上述電話op如果list.size < len否則調用other

10

如果你堅持使用模式匹配(也許你想包括更多比賽情況?),你可以使用一個保護條件吧:

list match { 
    case l if(l.size <= 3) => op(l) 
    case l => other(l) 
} 
+2

使用lengthCompare將比較列表長度與3更有效 –