为haskell中的元组列表分配秩
如何为Haskell中的元组列表分配秩(考虑到关系)?理想情况下,如果想要一个给定元组列表的函数,它将返回一个具有秩的元组列表 样本输入(假设根据每个元组的snd按升序排列): 样本输出:为haskell中的元组列表分配秩,haskell,tuples,rank,Haskell,Tuples,Rank,如何为Haskell中的元组列表分配秩(考虑到关系)?理想情况下,如果想要一个给定元组列表的函数,它将返回一个具有秩的元组列表 样本输入(假设根据每个元组的snd按升序排列): 样本输出: [("a",1),("b",2),("c",3),("d",4),("e",5.5),("f",5.5),("g",7),("h",8),("i",9),("j",10)] 注意“e”和“f”并列,所以它们的秩(5和6)相加并除以2。更一般地说,特定列组[i..j]范围内的任意n个数量的连接都将接收相同的和
[("a",1),("b",2),("c",3),("d",4),("e",5.5),("f",5.5),("g",7),("h",8),("i",9),("j",10)]
注意“e”和“f”并列,所以它们的秩(5和6)相加并除以2。更一般地说,特定列组[i..j]范围内的任意n个数量的连接都将接收相同的和[i..j]/n列组
注意:我今天刚刚开始学习Haskell(来自Python和Java),因此我更愿意提供有用的提示,而不是透露答案。足以让我找到正确的解决方案。谢谢
编辑/第二部分问题:好的,多亏了jamshidh、chunksof50和leftaroundabout,我想出了
sortStudents xs = sortBy (compare `on` snd) xs
prerankStudents xs = groupBy ((==) `on` (snd.fst)) (zip (sortStudents xs) [1..])
rankStudents xs = concat [ [if length ys > 1 then (a, fromIntegral (sum (map snd ys)) / fromIntegral (length ys)) else (a,fromIntegral c) | ((a,b),c) <- ys] | ys <- (prerankStudents . sortStudents) xs ]
sortStudents xs=sortBy(compare`on`snd)xs
prerankStudents xs=groupBy(==)`on`(snd.fst))(zip(sortStudents xs)[1..]
rankStudents xs=concat[[如果长度ys>1,那么(a,from integral(sum(map snd ys))/from integral(length ys)),或者(a,from integral c)|((a,b),c)以下是一些您会发现有用的函数
Data.List.groupBy
Data.List.sortBy --you won't actually need this if you assume the input is ordered, but I threw it in anyway
Data.Function.on
(==)
您可以按第二项对数据进行分组,然后使用递归输出值,增加每个项目的排名…如果组中的项目数大于一,只需增加该值,并根据组中的排名输出值的平均值
这就足够让你在不给出完整答案的情况下继续了。如果列表操作系统确实已经排序(),那么这或多或少会用一个简单的枚举来替换snd
字段。所以首先要做枚举!这在Haskell中非常简单:zip results1[1..]
[(("a",12),1),(("b",56),2),(("c",61),3),(("d",73),4),(("e",75),5),(("f",75),6),(("g",81),7),(("h",82),8),(("i",91),9),(("j",97),10)]
剩下要做的主要是均衡重复项。我首先将它们分组:groupBy((==)`on`(snd.snd))
gives
[[(("a",12),1)],[(("b",56),2)],[(("c",61),3)],[(("d",73),4)],[(("e",75),5),(("f",75),6)],[(("g",81),7)],[(("h",82),8)],[(("i",91),9)],[(("j",97),10)]]
请注意,除了“e”
和“f”
共享一个列表外,所有元素现在都在一个单例列表中
然后,对这些列表中的每一个进行平均排名。这可以很好地写成一个带有模式匹配的列表理解,这是一个很好的练习。您要求的提示和技巧,因此这里先介绍一些技巧:
用于查找有关函数的信息
使用类型签名并注意它们
通过使用纯函数式的方法学习haskell,您将学到更多,因此,除了最终管道之外,请避免使用IO monad,否则您将像以前一样完成写作
递归是你的扳手,但高阶函数是你的重型机器
写很多简单的小函数,而不是一个解决问题的大函数
暗示
zip
,zipWith
-组合列表。在某个时刻,您将需要无限列表[1..]
groupBy
。当我们在这个领域工作时,在某个时候可以查看一下
上的函数,但通常情况下,类型签名没有多大帮助,您希望看到示例
sum
,length
,map
。map
是一个基本的列表处理函数。map
是一个基本的列表处理函数。使用类型来确定您可以使用fst.snd
或snd.fst
或fst.fst
或snd.snd
map
更多,最后你需要concat
您可能最终定义了其他功能,或者最终以一种非常不同的方式进行定义,但了解这些功能将培养您的Haskell技能
[(("a",12),1),(("b",56),2),(("c",61),3),(("d",73),4),(("e",75),5),(("f",75),6),(("g",81),7),(("h",82),8),(("i",91),9),(("j",97),10)]
[[(("a",12),1)],[(("b",56),2)],[(("c",61),3)],[(("d",73),4)],[(("e",75),5),(("f",75),6)],[(("g",81),7)],[(("h",82),8)],[(("i",91),9)],[(("j",97),10)]]