我有一个清单:
[(HOUSE, 1), (FRAME, 2), (WATER, 3), (WIND, 4), (CREST, 5)]
我希望像这样反转它:
[(CREST, 5), (WIND, 4), (WATER, 3), (FRAME, 2), (HOUSE, 1)]
我该怎么做?
一位朋友告诉我,有一种方法可以反转它,但首先你需要反转元组,因为有一个功能只有"看起来"在排序的第一个元素,因为我按照单词后面的数字进行排序,我需要先将数字放入。
例:(5, CREST)
我真的需要这样做吗?如果我这样做,接下来我该怎么做?因为我已经有一个函数可以反转元组的顺序。现在我需要反转整个列表。
Obs。:列表是用户输入。
如果有办法在不反转元组的情况下进行,请告诉我。也许我试图以一种困难的方式做一件简单的事情。
请解释代码如何以简单的方式工作,因为我是初学者。
答案 0 :(得分:6)
您可以使用reverse
(从Prelude
导入):
reverse [(HOUSE, 1), (FRAME, 2), (WATER, 3), (WIND, 4), (CREST, 5)]
-- [(CREST, 5),(WIND, 4),(WATER, 3),(FRAME, 2),(HOUSE, 1)]
无需对列表中的元组进行排序和/或反转。
答案 1 :(得分:2)
自己尝试并实施它是有益的。但是,这是前奏的一种方式:
reverse = foldl (flip (:)) []
答案 2 :(得分:2)
正如其他答案所述,简单地反转列表并不需要反转你的元组或任何类型的排序;您可以使用reverse
中的Prelude
功能。但是,如果您确实希望根据元组中的数字排序,那么这是一个稍微复杂的问题。
来自sort
的{{1}}功能可能是您朋友所指的功能。它使用Data.List
函数比较列表的元素,然后根据该列表对列表进行排序。正如你的朋友所指出的,元组compare
的实现是比较每个元组的第一个元素,如果它们相等,则查看第二个元素等。
但是,compare
中有一个名为Data.List
的更通用的排序功能。它有类型签名:
sortBy
基本上,它与sortBy :: (a -> a -> Ordering) -> [a] -> [a]
相同,只是不是调用sort
来比较两个值并确定它们的顺序,而是指定它如何比较值。由于您希望通过比较它们的第二个值来比较这些元组,因此您要使用的函数是compare
(返回元组的第二个元素)。我们现在有这个:
snd
为了按降序排序,我使用了λ> :m + Data.List
λ> let list = [(WATER, 3), (WIND, 4), (CREST, 5), (HOUSE, 1),(FRAME, 2)]
λ> let cmp a b = compare (snd a) (snd b)
λ> sortBy cmp list
[(HOUSE,1),(FRAME,2),(WATER,3),(WIND,4),(CREST,5)]
λ> sortBy (flip cmp) list
[(CREST,5),(WIND,4),(WATER,3),(FRAME,2),(HOUSE,1)]
中的flip
函数,它只是颠倒了两参数函数的参数顺序。
作为最后一点,我将从Prelude
调出comparing
函数。在不过多详细介绍的情况下,通过在相同的代码片段中使用它,可以非常容易地理解其功能:
Data.Ord
给定一个函数(称之为λ> :m + Data.List Data.Ord
λ> let list = [(WATER, 3), (WIND, 4), (CREST, 5), (HOUSE, 1),(FRAME, 2)]
λ> sortBy (comparing snd) list
[(HOUSE,1),(FRAME,2),(WATER,3),(WIND,4),(CREST,5)]
λ> sortBy (flip $ comparing snd) list
[(CREST,5),(WIND,4),(WATER,3),(FRAME,2),(HOUSE,1)]
),f
将返回一个比较函数,该函数首先在两个值上调用comparing
,然后比较这些值。基本上正是函数f
在第一个例子中做了什么,但更简洁和可读。