在Haskell中反转列表

时间:2014-07-26 01:16:44

标签: list haskell

我有一个清单:

[(HOUSE, 1), (FRAME, 2), (WATER, 3), (WIND, 4), (CREST, 5)]

我希望像这样反转它:

[(CREST, 5), (WIND, 4), (WATER, 3), (FRAME, 2), (HOUSE, 1)]

我该怎么做?

一位朋友告诉我,有一种方法可以反转它,但首先你需要反转元组,因为有一个功能只有"看起来"在排序的第一个元素,因为我按照单词后面的数字进行排序,我需要先将数字放入。

例:(5, CREST)

我真的需要这样做吗?如果我这样做,接下来我该怎么做?因为我已经有一个函数可以反转元组的顺序。现在我需要反转整个列表。

Obs。:列表是用户输入。

如果有办法在不反转元组的情况下进行,请告诉我。也许我试图以一种困难的方式做一件简单的事情。

请解释代码如何以简单的方式工作,因为我是初学者。

3 个答案:

答案 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)]

Live demo

无需对列表中的元组进行排序和/或反转。

答案 1 :(得分:2)

自己尝试并实施它是有益的。但是,这是前奏的一种方式:

reverse =  foldl (flip (:)) []
  • flip接受一个函数并返回相同的函数,其参数被反转。
  • foldl将在列表的所有元素之间交错一个函数
  • ":"是一个将项目附加到列表头部的cons函数

答案 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在第一个例子中做了什么,但更简洁和可读。