首页 文章

将等级分配给haskell中的元组列表

提问于
浏览
5

如何将排名分配给Haskell中的元组列表(考虑到关系)?理想情况下,想要一个给出元组列表的函数,会返回一个带有排名的元组列表 .

样本输入(假设基于每个元组的snd以升序排序):

results1 = [("a",12),("b",56),("c",61),("d",73),("e",75),("f",75),("g",81),("h",82),("i",91),("j",97)]

样本输出:

[("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个关系都将被接收sum [i..j] / n的相同等级 .

NOTE: 我今天刚刚开始学习Haskell(来自Python和Java),所以我更愿意提供有用的提示而不是揭示答案 . 足以让我找到合适的解决方案 . 谢谢!

EDIT/PART 2 QUESTION: 好的,所以感谢jamshidh,chunksof50,并且左右我想出了

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和prerankStudents相对满意,但是rankStudents感觉有点像我'm writing python again (list comprehension), although I'我不确定在这种情况下它是好还是坏 . 我尝试用case..of递归地实现rankStudents,但是平滑的错误似乎超出了我的脑海 . 这是代码,如果有人要向我详细解释为什么它不起作用 .

rankStudents xs = let ss = prerankStudents xs
              rankStudents' ys = case ys of [] -> []
                            [((a,b),c)] -> [(a,c)]
                            (((a1,b1),c1):zs) -> [((fst.fst) tup, fromIntegral (sum (map snd ys)) / fromIntegral (length ys)) | tup <- ys]              
                            y:ys -> rankStudents' y ++ rankStudents' ys
              in rankStudents' ss

3 回答

  • 4

    以下是一些有用的功能....

    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
    (==)
    

    您可以按第二项对数据进行分组,然后使用递归输出值,增加每个项的等级....如果组中的项数大于1,则只增加此值,并输出值根据组中的排名的平均值 .

    这足以让你在没有给出完整答案的情况下前进 .

  • 3

    您要求的提示和提示,所以首先提示:

    • 使用hoogle查找有关功能的信息 .

    • 使用类型签名并注意它们 .

    • 你'll learn more from learning haskell by doing things the pure functional way, so avoid the IO monad except for final plumbing, otherwise you'最终会像以前那样写作 .

    • 递归是你的扳手,但更高阶的功能是你的重型机械 .

    • 编写许多简单的小函数,而不是一个可以解决的大函数

    提示

    • zipzipWith - 组合列表 . 在某些时候你会想要无限列表 [1..] .

    • groupBy . 值得看看函数 on ,而我们're in this area, but that'是一个不常见的类型签名没有多大帮助,你想看到这些例子 .

    • sumlengthmap . 您将不得不通过 map 获得创意; map 是一个基本的列表处理函数 . 使用类型来确定您可以使用 fst.sndsnd.fstfst.fstsnd.snd

    • map 更多,最后你需要 concat

    您最终可能会定义其他函数,或者最终以不同的方式使用它们,但了解这些函数将构建您的Haskell技能 .

  • 2

    如果确实列表已经排序(if not, trivial to use sortBy comparing snd),那么这或多或少用简单的枚举替换 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)]
    

    's left to do is mainly equalising duplicates. I'首先将那些分组: groupBy ((==)on(snd.snd)) 给出

    [[(("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" 共享一个列表之外,所有元素现在都是单独列出的 .

    然后,对于每个列表,您平均排名 . 这可以作为列表理解与模式匹配很好地编写,这是一个你可以作为练习做的好事 .

相关问题