Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List Haskell的F1结果_List_Haskell - Fatal编程技术网

List Haskell的F1结果

List Haskell的F1结果,list,haskell,List,Haskell,最简单的解决方案是什么 定义一个函数,用于在函数“f1Results”中计算公式1比赛系列。该参数是一个列表,其元素是基于每次大奖赛结果的列表。每份名单应包含GP结果中列出的参赛者姓名(获胜者为名单的第一名)。该功能的结果必须是一个F1飞行员名单,按整个F1赛季的积分数排序 f1Results :: [[String]] -> [String] 每个职位都必须获得以下列表中的分数(同样,25分代表优胜者)得分得分得分(例如:排名第一的25分,排名第二的18分,等等) 一种方法是使用

最简单的解决方案是什么

定义一个函数,用于在函数“f1Results”中计算公式1比赛系列。该参数是一个列表,其元素是基于每次大奖赛结果的列表。每份名单应包含GP结果中列出的参赛者姓名(获胜者为名单的第一名)。该功能的结果必须是一个F1飞行员名单,按整个F1赛季的积分数排序

   f1Results :: [[String]] -> [String]
每个职位都必须获得以下列表中的分数(同样,25分代表优胜者)得分得分得分(例如:排名第一的25分,排名第二的18分,等等)


一种方法是使用地图,其中键是司机的名字,值是分数。要将分数与f1results中每个子列表的驱动因素相关联,可以使用PointsCorning压缩子列表。函数可以获取每个压缩的子列表,并为地图中遇到(或新添加到)的每个驱动程序添加分数。然后根据这些值对地图进行排序

比如说,

import qualified Data.Map as M
import Data.List(sortBy)

pointsScoring :: [Int] 
pointsScoring = [25, 18, 15, 12]

f1List :: [[String]]
f1List = [["alex","bart","cecyl","dark"]
         ,["dark","bart","cecyl","alex"]
         ,["bart","cecyl","alex","dark"]]

f1Results :: [[String]] -> [String]
f1Results list = map fst . sortBy (\(n1,s1) (n2,s2) -> compare s2 s1) . M.toList 
               $ foldr f M.empty (concatMap (zip pointsScoring) list)
  where f (score,name) results = M.insertWithKey updateMap name score results
        updateMap key newValue oldValue = newValue + oldValue
输出:

*Main> f1Results f1List
["bart","alex","dark","cecyl"]

你有一个关于分数的常数

scoring :: [Int]
scoring = [25, 18, 15, 12, 10, 8, 6, 4, 2, 1]
然后,你需要一种方法将一名司机与他们得到的分数配对。无论何时在Haskell中配对两个对象,典型的选择是使用元组。从两个列表构造元组列表的最简单方法是
zip
函数:

zip :: [a] -> [b] -> [(a, b)]
在这种情况下,可用于分配比赛分数:

assignScores :: [String] -> [(String, Int)]
assignScores race = zip race scoring
现在,我们需要一种方法来计算每一场比赛中一名车手的总分。我们希望能够像这样

[("Bob", 12), ("Joe", 10), ("Bob", 18), ("Joe", 25)]
进入

最简单的方法是列出所有比赛的所有分数

assignAllScores :: [[String]] -> [(String, Int)]
assignAllScores races = concatMap assignScores races
然后我们可以使用
Data.List
中的
sortBy
来获得彼此相邻的所有相同名称

sortBy :: (a -> a -> Ordering) -> [a] -> [a]
compare :: Ord a => a -> a -> Ordering

sortByDriver :: [(String, Int)] -> [(String, Int)]
sortByDriver races = sortBy (\(n1, s1) (n2, s2) -> compare n1 n2) races
然后我们可以使用
groupBy
(也可以从
Data.List
)按名称对它们进行分组

groupBy :: (a -> a -> Bool) -> [a] -> [[a]]

groupByDriver :: [(String, Int)] -> [[(String, Int)]]
groupByDriver races = groupBy (\(n1, s1) (n2, s2) -> n1 == n2) races
但这给了我们一个类似的列表

[[("Bob", 12), ("Bob", 18)], [("Joe", 10), ("Joe", 25)]]
我们现在需要一种将其转换为表单的方法

[("Bob", [12, 18]), ("Joe", [10, 25])]
所有的分数都会重新汇总到一个列表中,我们根本不会重复这些名字。这只是一个练习

aggregateScores :: [[(String, Int)]] -> [(String, [Int])]
然后我们最终可以计算出这些分数的总和

sumScores :: [(String, [Int])] -> [(String, Int)]
sumScores races = map (\(name, scores) -> (name, sum scores)) races
最后,我们可以按分数排序,让每个人都井然有序

sortByScore :: [(String, Int)] -> [(String, Int)]
sortByScore races = sortBy (\(n1, s1) (n2, s2) -> compare s2 s1) races
请注意,我使用了
compare s2 s1
而不是
compare s1 s2
,这意味着它将按降序而不是升序排序

最后一步是去掉分数,现在我们有了从赢家到输家的车手名单

removeScores :: [(String, Int)] -> [String]
removeScores races = map fst races
所以要把所有的东西组合成一个函数

f1Results :: [[String]] -> [String]
f1Results races =
    removeScores $
    sortByScore  $
    sumScores    $
    aggregateScores $
    groupByDriver $
    sortByDriver $
    assignAllScores races

有几种技巧可以缩短此代码,即
Data.Function.on
Data.Ord.comparing
,以及
Control.Arrow
中的有趣操作符。不要把这当作家庭作业,我只是想展示一个使用更少代码的替代方案

import Data.List
import Data.Function (on)
import Data.Ord (comparing)

scoring :: [Int]
scoring = [25, 18, 15, 12, 10, 8, 6, 4, 2, 1]

f1Results :: [[String]] -> [String]
f1Results =
    map fst . sortBy (on (flip compare) snd) .
    map ((head *** sum) . unzip) .
    groupBy (on (==) fst) . sortBy (comparing fst) .
    concatMap (`zip` scoring)
或者使用
Data.Map

import Data.Map (assocs, fromListWith)
import Data.List
import Data.Ord (comparing)

scoring :: [Int]
scoring = [25, 18, 15, 12, 10, 8, 6, 4, 2, 1]

f1Results :: [[String]] -> [String]
f1Results =
    reverse . map fst . sortBy (comparing snd) .
    assocs . fromListWith (+) .
    concatMap (`zip` scoring)

地图zip、concat、groupBy、地图总和、orderBy、地图fst…-3???为什么?虽然我没有对这个问题投反对票,但我怀疑反对票的人对你没有试图解决这个问题的事实做出了反应。坦率地说,对一些选民来说,这可能是一个“请为我做家庭作业”的问题。它通常有助于说明问题的来源(来自书本的练习?网站?家庭作业?),展示你的一些尝试(甚至是一些非正式的想法,不一定是一些Haskell代码),并说明你需要帮助的要点。没有家庭作业,只作为我学习的任务。:)是的。。。我明白了。。但是人们看到我是新来的。。那如果我不知道如何发布东西,为什么还要奉献给我呢。。现在我知道了,因为你告诉我。。但是它们有点粗鲁:/当然我可以展示一些尝试,我只是删除了它们,因为它们甚至不足以编译。正如我所说,我对这一点还不熟悉。我想我选择了一个艰难的开始。但逻辑上似乎很简单。我可以按照你的代码。。这是一个精巧的人!但无法找出如何使聚合存储始终出现一些错误。。当我试图编译它时,它还说:“类型签名中缺少变量“zip”的绑定:/。。。最后那些缩短的版本非常酷。。希望有一天我能像你一样懂这门语言……:)请帮我完成这个。我认为这是一个挑战,但我失败了。另外:这里缺少了一些东西。你在哪里创建了一个种族列表?如果我有这样一个列表就太好了:
[Vettel、Ricciardo、Rosberg、Hamilton、Raikonen、Alonso、Massa、Perez、Magnusen、Button]
从这个列表中,我可以创建任意多个不同位置的人。。。啊,男人太难了:(@MarkedOne 1)你不需要包含没有定义的类型签名。我想我应该在上面说得更清楚些,我只是把它们放在那里作为参考,以了解它们的类型签名是什么。只要确保导入了正确的库,它们就在范围内。2) 我刚刚用三名赛车手
Bob
Joe
Steve
快速输入了一些东西,但是如果你想从车手姓名列表中生成一组示例数据,请查看
数据中的
排列
函数。list
,你可以使用它生成所有可能的排列,然后将前10个左右作为输入。感谢您介绍我使用fromListWith和中缀作为flip。为什么它总是说:“缺少类型签名中变量“sortBy”的绑定。”。。对于其他定义:/
import Data.List
import Data.Function (on)
import Data.Ord (comparing)

scoring :: [Int]
scoring = [25, 18, 15, 12, 10, 8, 6, 4, 2, 1]

f1Results :: [[String]] -> [String]
f1Results =
    map fst . sortBy (on (flip compare) snd) .
    map ((head *** sum) . unzip) .
    groupBy (on (==) fst) . sortBy (comparing fst) .
    concatMap (`zip` scoring)
import Data.Map (assocs, fromListWith)
import Data.List
import Data.Ord (comparing)

scoring :: [Int]
scoring = [25, 18, 15, 12, 10, 8, 6, 4, 2, 1]

f1Results :: [[String]] -> [String]
f1Results =
    reverse . map fst . sortBy (comparing snd) .
    assocs . fromListWith (+) .
    concatMap (`zip` scoring)