(新手警报)
我正在尝试使用以下签名编写函数,因为我在标准库中找不到类似的东西:
deleteFromList :: (b -> a -> Bool) -> b -> [a] -> (Maybe a, [a])
-- Example 1: Item found in the list, and deleted
deleteFromList (\(id1, name1), (id2, name2) -> id1==id2) 3 [(1, "Jack"), (2, "Jill"), (3, "Joe"), (4, "Jimmy")]
-- returns (Just (3, "Joe"), [(1, "Jack"), (2, "Jill"), (4, "Jimmy")]
-- Example 2: Item not found in list
deleteFromList (\(id1, name1), (id2, name2) -> id1==id2) 5 [(1, "Jack"), (2, "Jill"), (3, "Joe"), (4, "Jimmy")]
-- returns (Nothing, [(1, "Jack"), (2, "Jill"), (3, "Joe"), (4, "Jimmy")]
我知道这可以通过调用Data.List.find
和Data.List.deleteBy
来编写,但这会导致列表的两次遍历。我想让我的生活更加艰难,只需一次遍历即可。
答案 0 :(得分:2)
您可以使用foldr
轻松实现该功能,如下所示:
deleteFromList :: (b -> a -> Bool) -> b -> [a] -> (Maybe a, [a])
deleteFromList p target = foldr folder (Nothing, [])
where
folder x (Nothing, xs) | p target x = (Just x, xs)
folder x (m, xs) = (m, x : xs)
虽然我确信经验丰富的Haskellers(我不是)将能够提出一个单行...
用法示例:
*Q35115395> deleteFromList (\x y -> x == fst y) 3 [(1, "Jack"), (2, "Jill"), (3, "Joe"), (4, "Jimmy")]
(Just (3,"Joe"),[(1,"Jack"),(2,"Jill"),(4,"Jimmy")])
*Q35115395> deleteFromList (\x y -> x == fst y) 5 [(1, "Jack"), (2, "Jill"), (3, "Joe"), (4, "Jimmy")]
(Nothing,[(1,"Jack"),(2,"Jill"),(3,"Joe"),(4,"Jimmy")])
答案 1 :(得分:1)
一个简单的递归解决方案:
deleteFromList :: (b -> a -> Bool) -> b -> [a] -> (Maybe a, [a])
deleteFromList p b (x: xs) | p b x = (Just x, xs)
| otherwise = let (y, rest) = deleteFromList p b xs in
(y, x: rest)
deleteFromList _ _ [] = (Nothing, [])
答案 2 :(得分:1)
@Mark Seemann干得好,正如Chi建议的那样,用分区改进会更好
Prelude DL> let myFunction x = partition ((==x).(fst))
示例:
Prelude DL> myFunction 1 [(1,2),(2,9)]
([(1,2)],[(2,9)])
Prelude DL> myFunction 5 [(1, "Jack"), (2, "Jill"), (3, "Joe"),(4, "Jimmy")]
([],[(1,"Jack"),(2,"Jill"),(3,"Joe"),(4,"Jimmy")])
Prelude DL> myFunction 3 [(1, "Jack"), (2, "Jill"), (3, "Joe"),(4, "Jimmy")]
([(3,"Joe")],[(1,"Jack"),(2,"Jill"),(4,"Jimmy")])
这更通用:
Prelude> let myFunction g x = partition (g .fst)
Prelude> myFunction (==3) 3 [(1, "Jack"), (2, "Jill"), (3, "Joe"),(4, "Jimmy")]
([(3,"Joe")],[(1,"Jack"),(2,"Jill"),(4,"Jimmy")])