【问题标题】:Breaking a list on a given value into a list of sublists将给定值的列表分解为子列表列表
【发布时间】:2021-08-23 13:26:49
【问题描述】:

multipleLists 函数需要从列表中删除给定值并返回列表列表。这些子列表对每个元素进行分组,直到它达到需要删除的值。发生这种情况时,会启动一个新的子列表。

input:           multipleLists 'b' "abcabc"
expected output: ["a","ca","c"]
actual output:   ["a","c","a","c"]

input:           multipleLists 1 [0,1,2,3,4,1,3,4]
expected output: [[0],[2,3,4],[3,4]]
actual output:   [[0],[2],[3],[4],[3],[4]]

我认为otherwise 的案例有问题,但我有点卡住了。

这是我的代码:

multipleLists :: Eq a => a -> [a] -> [[a]]
multipleLists value list = case list of 
    [] -> [] 
    [x] -> [[x]]
    x:xs 
        | value == x -> multipleLists value xs 
        | otherwise ->  [x] : (multipleLists value xs)

【问题讨论】:

  • multipleLists 1 [1] 的值是多少?
  • 一个空列表 - []
  • 你的第一个例子错了吗?那不应该是["a","ca","c"]

标签: list haskell recursion sublist


【解决方案1】:
multipleListsAllowEmpty value list = 
    let (beginning, end) = break (value ==) list
    in beginning : case end of
        [] -> []
        (_:xs) -> multipleListsAllowEmpty value xs

multipleLists value = filter (not . null) . multipleListsAllowEmpty

在这里,我们从Data.List 导入break

我们可以更简洁地表达multipleListsAllowEmpty

maybeTail [] = Nothing
maybeTail (_:xs) = Just xs

multipleListsAllowEmpty value = 
    toList . unfoldr (fmap maybeTail . break (value ==))

我们从Data.List.NonEmpty 导入unfoldrtoList

【讨论】:

  • 有没有办法在不导入任何东西的情况下做到这一点?
  • 您的基于unfoldr 的代码不会进行类型检查。如果您将fmap 替换为traverse,它会这样做,但它会跳过输出中的最后一组。
【解决方案2】:

这是您使用累加器的修改版本 - 除了reverse(您可以通过更改累加器的构建方式来删除它)之外,它不使用任何外部的东西:

multipleLists :: Eq a => a -> [a] -> [[a]]
multipleLists value = go []
  where
  go [] [] = []
  go [] (x:xs)
    | x == value = go [] xs
    | otherwise = go [x] xs
  go acc [] = [reverse acc]
  go acc (x:xs)
    | x == value = reverse acc : go [] xs
    | otherwise = go (x:acc) xs

你的例子(见我上面的评论):

> multipleLists 'b' "abcabc"
["a","ca","c"]

> multipleLists (1 :: Int) [0,1,2,3,4,1,3,4]
[[0],[2,3,4],[3,4]]

【讨论】:

    【解决方案3】:

    multipleLists 0 [0, 0] 的预期值是多少?

    [] 还是[[]] 还是[[], []]

    这里有两种不同的解决方案,它们都基于正确的折叠。

    splitList :: Eq a => a -> [a] -> [[a]]
    splitList x = tail . foldr sx [[]] . (x:)
      where
        sx y ws@(zs:zss) | y == x    = [] : ws
                         | otherwise = (y:zs) : zss
    
    multipleLists :: Eq a => a -> [a] -> [[a]]
    multipleLists x = filter (not . null) . foldr sx [[]] . (x:)
      where 
        sx y ws@(zs:zss) | y == x    = [] : ws
                         | otherwise = (y:zs) : zss
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-21
    • 1970-01-01
    • 1970-01-01
    • 2016-12-04
    • 2017-05-07
    • 2014-07-07
    • 1970-01-01
    相关资源
    最近更新 更多