【问题标题】:operation on list of lists | how列表列表操作 |如何
【发布时间】:2012-03-17 16:20:18
【问题描述】:

当我在 Haskell 书中看到 concat 函数时,我想知道如何在 Haskell 中展平下面的列表。在 Python 中,我可以这样做,因为我可以在函数中检查它的类型。但在 Haskell 中我不能。如何展平下面的列表?

input: [[1, 2], [[2, 3], 5], [[[2, 3], [4, 5]], [2, 3]]]
output: [1, 2, 2, 3, 5, 2, 3, 4, 5, 2, 3]

【问题讨论】:

  • 注意 - 在 Haskell 中,如果您有嵌套列表,您通常会使用树而不是列表。在像 Haskell 这样的强类型语言中,嵌套的结构必须反映在列表类型中——有时这很好,但通常你真的想要一棵树,而不是类型只需要考虑元素而不是结构。标准库中有一个模块Data.Tree,它是一棵玫瑰树,或者很容易自己滚动。
  • 您的输入甚至不是 Haskell 中的有效列表。

标签: haskell


【解决方案1】:

您不能在 haskell 中创建具有不同深度的列表。它不会进行类型检查。 [[a]][[[a]]] 的类型不同。此功能将解决您的问题,但仅限于具有相同深度的列表。

flat::[[a]] -> [a]
flat [] = []
flat l:ls = l ++ flat ls 

【讨论】:

  • 其实这个函数已经存在了,叫做concat
  • 感谢您的提醒。自从我编写haskell以来已经有很长时间了,我不确定是否有这样的功能,所以为了安全起见,我自己写了
  • 在这个问题中,有一级列表 - [[a]],但如果不止于此,则应该多次调用 concat。 concat 只会展平一层。当然,这不适用于上述问题,但需要注意。
  • 在 ghci 8.4.3 中,第三个定义应该使用像 flat (l:ls) = l ++ (flat ls) 这样的括号来写
【解决方案2】:

正如已经指出的,在 Haskell 中不能有任意的嵌套列表。最接近的东西(没有使用花哨的编译指示的脏类型类黑客)是这样的:

data Nested a = L a | B [Nested a]

flatten :: Nested a -> [a]
flatten (L x) = [x]
flatten (B xs) = concatMap flatten xs  

print $ flatten $ B[B[L 1,L 2],B[B[L 2,L 3],L 5],B[B[B[L 2,L 3],B[L 4, L 5]],B[L 2,L 3]]]
--[1,2,2,3,5,2,3,4,5,2,3]

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多