展平列表列表
Posted
技术标签:
【中文标题】展平列表列表【英文标题】:Flatten a list of lists 【发布时间】:2012-03-19 10:12:14 【问题描述】:我必须编写一个扁平化列表的函数。
例如flatten [] = []
或flatten [1,2,3,4] = [1,2,3,4]
或flatten [[1,2],[3],4,5]] = [1,2,3,4,5]
我无法根据给定的 flatten 函数匹配类型。
这是我所拥有的:
data A a = B a | C [a] deriving (Show, Eq, Ord)
flatten::(Show a, Eq a, Ord a)=>A a -> A a
flatten (C []) = (C [])
flatten (C (x:xs) ) = (C flatten x) ++ (C flatten xs)
flatten (B a) = (C [a])
据我所知,问题是++
运算符期望它的两个参数都有一个列表,我试图给它一些A
类型的东西。我添加了 A
类型,因此该函数可以获取单个元素或元素列表。
有没有人知道一种不同的方法来做到这一点,或者解释我可以做些什么来修复类型错误?
【问题讨论】:
我不确定你到底想要什么。也许flatten :: A [a] -> A a; flatten (B xs) = C xs; flatten (C xss) = C (concat xss)
会帮助你?基本上,您不能编写 flatten 以便它获取不同嵌套的列表并对它们执行不同的操作,除非您将它们包装成新类型并通过构造函数区分情况。
你的函数类型应该是[[a]] -> [a]
。这意味着flatten []
有效,flatten [[1,2,3,4]]
有效,但flatten [1,2,3,4]
无效。 [1,2,3,4]
不是列表列表。如果您考虑到这一点并从头开始,摆脱您的特殊类型,您会发现它会容易得多。
operation on list of lists | how的可能重复
【参考方案1】:
通过列表理解展平。
flatten arr = [y | x<- arr, y <- x]
【讨论】:
【参考方案2】:这一个班轮将完成这项工作。尽管正如 Malin 提到的,类型签名不同:
flatten :: [[a]] -> [a]
flatten xs = (\z n -> foldr (\x y -> foldr z y x) n xs) (:) []
简单测试
frege> li = [[3,4,2],[1,9,9],[5,8]]
frege> flatten li
[3,4,2,1,9,9,5,8]
【讨论】:
关键是该函数应该适用于简单列表和嵌套列表。您的作品仅适用于简单列表。【参考方案3】:首先,A 类型是在正确的轨道上,但我不认为它是完全正确的。您希望它能够展平任意嵌套的列表,因此“A a”类型的值应该能够包含“A a”类型的值:
data A a = B a | C [A a]
其次,函数的类型应该略有不同。您可能希望它只返回 a 的列表,而不是返回类型为“A a”的值,因为根据定义,该函数始终返回一个平面列表。所以类型签名是这样的:
flatten :: A a -> [a]
还要注意,不需要类型类约束——这个函数是完全通用的,因为它根本不查看列表的元素。
这是我的实现:
flatten (B a) = [a]
flatten (C []) = []
flatten (C (x:xs)) = flatten x ++ flatten (C xs)
【讨论】:
flatten (B a) = [a]; flatten (C xs) = flatten =<< xs
【参考方案4】:
有点不清楚您要的是什么,但展平列表列表是一个标准函数,在前奏中称为concat
,类型签名为[[a]] -> [a]
。
如果您像上面开始的那样创建嵌套列表的数据类型,也许您想将数据类型调整为如下所示:
data Lists a = List [a] | ListOfLists [Lists a]
然后你可以将它们展平为一个列表;
flatten :: Lists a -> [a]
flatten (List xs) = xs
flatten (ListOfLists xss) = concatMap flatten xss
作为测试,
> flatten (ListOfLists [List [1,2],List [3],ListOfLists [List [4],List[5]]])
[1,2,3,4,5]
【讨论】:
以上是关于展平列表列表的主要内容,如果未能解决你的问题,请参考以下文章