如何从列表中删除,返回已删除的元素,并返回“已修改”列表

时间:2016-01-31 15:12:29

标签: haskell functional-programming list-comprehension

(新手警报)

我正在尝试使用以下签名编写函数,因为我在标准库中找不到类似的东西:

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.findData.List.deleteBy来编写,但这会导致列表的两次遍历。我想让我的生活更加艰难,只需一次遍历即可。

3 个答案:

答案 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")])