2017-04-23 76 views
4

我正在寫一個函數,它調用後面的整數和兩個整數列表作爲參數。如果num1出現在列表中並且num2出現在列表afternum1中,則列表num1中的num2應該返回True。 (不一定在之後)。一個haskell函數來測試一個整數是否出現在另一個整數之後

after::[Int]->Int->Int->Bool 
after [] _ _=False 
after [x:xs] b c 
    |x==b && c `elem` xs =True 
    |x/=b && b `elem` xs && b `elem` xs=True 

這是我到目前爲止,我最大的問題是,我不知道如何強制num2後num1。

+0

如果num1,num2中沒有任何一個出現在列表中,例如: '[2,3,4] 5 2'或'在[2,3,4] 2 5'之後'或'在[2,3,4] 1 7'之後''之後? – niceman

+0

順便說一下,你的函數不是遞歸的,它應該是 – niceman

+0

那麼它應該返回假 – user3358850

回答

1

您可以將其分爲兩部分:第一部分將找到第一個出現的num1。之後,你只需要刪除它之前的所有元素,並檢查num2是否在列表的其餘部分。

第一部分有一個標準功能elemIndex。第二個只是elem

import Data.List (elemIndex) 

after xs x y = 
    case x `elemIndex` xs of 
     Just i -> y `elem` (drop (i + 1) xs) 
     Nothing -> False 
+0

但是你也將第一部分分爲兩部分。 'elemIndex'和'drop'的組合意味着你需要兩次檢查'xs'的第一部分,如果第一次出現'x'的地方接近結尾,那麼這很糟糕。在Chris Penner的回答中,最好使用'dropWhile'完成。 –

7

有幾種不同的方法來處理這個問題;雖然這很容易直接進行遞歸,但如果還有其他選項,請避免明確使用遞歸 。

這是使用一些列表實用程序的簡單版本。請注意,這是一個Haskell成語,我們正在操作的對象通常是最後一個參數。在這種情況下,切換參數讓我們把它寫成一個管道與它的隱式傳遞的第三個參數(列表):

after :: Int -> Int -> [Int] -> Bool 
after a b = elem b . dropWhile (/= a) 

希望這是很容易理解的;我們刪除列表中的元素,直到我們點擊一​​個a,假設我們找到一個我們檢查其餘列表中是否有b。如果沒有a,這個列表是[],顯然那裏沒有b,所以它按預期返回False。

如果'a'和'b'相等,您還沒有具體說明會發生什麼情況,所以我會留給您以適應這種情況。提示:添加一個tail某處;)

這裏有一對夫婦的其他方法,如果你有興趣:

這是非常容易使用的摺疊處理;

我們有三種模型。或者我們正在尋找第一個元素,或者我們正在尋找第二個元素,或者我們已經找到它們(以正確的順序)。

data State = 
    FindA | FindB | Found 
    deriving Eq 

然後,我們可以'摺疊'(又名減少)列表下來的結果是否匹配。

after :: Int -> Int -> [Int] -> Bool 
after a b xs = foldl go FindA xs == Found 
    where 
    go FindA x = if x == a then FindB else FindA 
    go FindB x = if x == b then Found else FindB 
    go Found _ = Found 

你也可以做到這一點遞歸,如果你喜歡:

after :: Int -> Int -> [Int] -> Bool 
after _ _ [] = False 
after a b (x:xs) 
    | x == a = b `elem` xs 
    | otherwise = after a b xs 

乾杯!

+1

不錯的選擇。如果我看到正確的話,其中一些可能不完全等同於'a == b'的情況。我的首選解決方案是第一個(緊湊型)和最後一個(易於閱讀)。 'foldl'似乎有點不合適,因爲你並不需要摺疊整個列表。 – chi

+0

@chi同意;他們沒有提到這種情況下的首選行爲,所以我並不擔心。 –

+1

'不。空值 。 dropWhile(/ = b)= elem b' – Cirdec

1

如果您想在不使用elemelemIndex的情況下實現它,可以包含一個子例程。例如:

after xs b c = go xs False 
    where go (x:xs) bFound 
      | x == b && not (null xs) = go xs True 
      | bFound && x == c  = True 
      | null xs     = False 
      | otherwise    = go xs bFound 
相關問題