Haskell构建元组列表

时间:2012-07-30 18:22:44

标签: haskell list-comprehension

我正在尝试构建一个元组列表。输入是元组[([char], int1, int2), ...]的列表,输出是元组列表,[([char], int1, int2, (int1/int2)), ...]。我知道下面的代码是错误的,因为我认为它正在构建一个元组列表[[(),(),(),()], [(),(),(),()]]

代码:

{- take a list of labels, values, and weights and return list of labels and fractions -}
fraclist [] = []
fraclist x = [ (y,r,q,z) : y <- first (head x) | r <- scnd (head x) | q <- last (head x) | z <- r/q ] : fraclist tail x

{- helper func to get values from tuples -}
frst (a,b,c) = a
scnd (a,b,c) = b
last (a,b,c) = c

如何获得所描述的正确输出格式?另外,我如何输出有序的元组列表,以便z按降序排列?

3 个答案:

答案 0 :(得分:1)

我想你只想

fraclist xs = [(y,r,q, r `quot` q) | (y,r,q) <- xs]

(注意:我使用quot代替(/),因为您将组件命名为int1int2。)

不使用列表推导的变体是

fraclist = map (\(y,r,q) -> (y,r,q, r `quot` q))

您的代码无法编译,在这种情况下,最好发布错误消息,以便人们可以一眼看出可能的原因。

您在

中的第一个<-上获得了解析错误
fraclist x = [ (y,r,q,z) : y <- first (head x) | r <- scnd (head x) | q <- last (head x) | z <- r/q ] : fraclist tail x

因为在生成的表达式与生成器表达式之间分隔的第一个(y,r,q,z) : y <- first (head x)之前的表达式|格式不正确。我认为这只是一个错字,你打算在那里使用|代替(:)

然后,您的列表理解中有多个|分隔符,如果没有ParallelListComp扩展名,则无效。但是,代码看起来并不像并行列表,理解就是你在这里尝试的,因为所有三个值都来自同一个列表。最后,最后一部分| z <- r/q再次没有格式良好,因为r/q不是可以在列表理解中绘制元素的列表。你可能打算let z = r/q那里。

答案 1 :(得分:1)

此代码无法编译(语法错误),但在修复后(我建议阅读syntax of list comprehensions(','s vs.'| s))并进行其他更改:

  • 使用了列表理解,它负责基本案例和列表上的映射 - 所以我能够消除fraclist [] = []head / tail / :业务

  • 使用模式匹配从输入元组中提取值 - 这通常比使用函数分离值更容易阅读

  • 为文档目的添加了显式类型签名

这就是我认为你的意思:

fraclist :: (Integral t1) => [(t, t1, t1)] -> [(t, t1, t1, t1)]
fraclist xs = [(x, y, z, div y z) | (x, y, z) <- xs]

我会把排序留给你。

答案 2 :(得分:0)

这是一个没有列表理解的简单解决方案:

import Data.List

-- (string, int1, int2) -> (string int1, int2, (int1/int2))
fraclist list = map generateTuple list
    where generateTuple (label, value, weight) = (label, value, weight, (value)/(weight)) 

sortFracListByValueWeightRatio list = sortBy sorter list
    where sorter (_,_,_,d) (_,_,_,h) = if d > h then GT else LT

testList = [("first",3.0,4.0), ("second",4.0,7.0)]

没什么特别的(我一周只使用过haskell)。

fraclist 通过将generateTuple函数映射到列表来工作。 generateTuple 函数只返回一个表单元组(标题,值,权重,值/权重)。 地图是一个内置函数,它只是将给定函数应用于列表的每个元素。

sortFracListByValueWeightRatio (对于长名称而言)使用内置的 sortBy 函数(来自Data.List),该函数使用自定义函数对给定列表进行排序比较项目。 Sorter 是我的商品比较器,它只是比较价值/重量比率并返回GT或LT(大于/小于)。因此,使用自定义比较器比较列表项,并根据其答案进行排序。

可读性的显着提高可能是使用类型来描述值而不仅仅是元组。我也在测试列表中使用双打,但这很容易改变。