2015-02-07 36 views
1

我想要一個替代filter,而不是丟棄錯誤的情況下,讓他們在一個單獨的地方。我想出了下面的內容,但不幸的是它顛倒了名單。顛倒列表順序,而不會增加複雜性

顯然我可以將x附加到ys或zs而不是cons,但這會顯着增加複雜性。

有沒有辦法在不增加複雜性的前提下保持順序?

splitBy :: (a -> Bool) -> [a] -> ([a],[a]) 
splitBy f xs = splitBy' f xs ([],[]) 
      where 
       splitBy' :: (a -> Bool) -> [a] -> ([a],[a]) -> ([a],[a]) 
       splitBy' _ [] result = result 
       splitBy' f (x:xs) (ys,zs) = if f x then splitBy' f xs (x:ys,zs) 
                else splitBy' f xs (ys,x:zs) 
+5

A [hoogle搜索](https://www.haskell.org/hoogle/?hoogle=%28a-%3EBool%29-%3E%5Ba%5D-%3E%28%5Ba%5D%2C%5Ba%5D%29)顯示該功能被稱爲「分區」。 – 2015-02-07 20:47:10

+0

感謝您的提示,要找到源代碼並查看它是否保持順序而不會增加複雜性。我是Haskell的新手,不習慣在除前奏之外的地方尋找。 – 2015-02-07 20:49:35

+2

學習[分區的源代碼](http://hackage.haskell.org/package/base-4.7.0.2/docs/src/Data-List.html#partition):它有效地將元素添加到末尾正在建立的清單(兩者)。懶惰模式('〜')允許將無限列表作爲輸入(例如'take 10 $ fst $ partition odd [1 ..]')。 – 2015-02-07 23:56:16

回答

3

正如其他人所說,該功能被稱爲partition,它是這樣工作的

partition :: (a -> Bool) -> [a] -> ([a], [a]) 
partition f = foldr (\x ~(yes,no) -> 
         if f x 
         then (x:yes,no) 
         else (yes,x:no)) 
        ([], []) 

的東西,除了真正的版本增加了一個明確的xs參數,也許是爲了幫助融合規則正常工作。如果時髦的懶惰模式匹配,使你緊張,你可以把它寫這樣的而不是:

partition f = foldr (\x r -> 
         if f x 
         then (x:fst r,snd r) 
         else (fst r,x:snd r)) 
        ([], []) 

如果foldr顯得神祕給你,你可以做到這一點是這樣的:

partition f [] = ([], []) 
partition f (x:xs) 
    | f x  = (x:fst r, snd r) 
    | otherwise = (fst r, x:snd r) 
    where r = partition f xs 
+0

你可以在最後一個版本中使用'(是,否)'模式,使用'where'。 – 2015-02-08 13:23:20

+0

@WillNess,這是真的,雖然改變第二個版本來匹配可能有點尷尬。 – dfeuer 2015-02-08 13:42:01