【问题标题】:Applying custom ordering to lists (to sort a list of lists)将自定义排序应用于列表(对列表列表进行排序)
【发布时间】:2012-03-08 04:27:24
【问题描述】:

在此页面上有一个如何使用自定义排序对列表进行排序的示例: http://zvon.org/other/haskell/Outputlist/sortBy_f.html

xxx a b  | odd a = LT
         | otherwise = GT

Input: sortBy xxx [1,2,3,4,5,6,7] 

Output: [1,3,5,7,6,4,2]

标准的小于顺序让我可以比较列表,例如

[1,2,3] < [0,4,5]

是假的。但这不适用于上面的示例函数:

Main> xxx [1,2,6] [1,7,3]
ERROR - Cannot infer instance
*** Instance   : Integral [a]
*** Expression : xxx [1,2,6] [1,7,3]

有没有一种简单的方法可以将这种顺序扩展到列表?

我想要这个功能的原因是使用 sortBy 来使用我的自定义排序对列表进行排序。

如果您提供示例解决方案代码、关于阅读内容的建议或介于两者之间的任何内容,我将不胜感激。我希望有一些内置的方法可以用语言做到这一点,而不是编写一个直接比较列表的函数。

【问题讨论】:

  • 请注意,sortBy 期望排序函数定义 total order,而 xxx 没有。例如,xxx y y 应该为任何y 返回EQ,如果xxx y z 为某些yz 返回LT,那么xxx z y 应该返回GT 等等。

标签: list sorting haskell


【解决方案1】:

您可以使用代码将比较函数转换为列表的比较函数:

import Data.Monoid (mconcat)
compareList :: (a -> b -> Ordering) -> [a] -> [b] -> Ordering
compareList _ [] [] = EQ
compareList _ (_:_) [] = GT
compareList _ [] (_:_) = LT
compareList comparer (x:xs) (y:ys) = 
    comparer x y `mappend` compareList comparer xs ys

现在您可以在两个列表中使用xxx

> compareList xxx [1,2,6] [1,7,3]
LT
> compareList xxx [2,2,6] [1,7,3]
GT

然后您可以使用比较器对嵌套列表进行排序:

> sortBy (compareList xxx) [[2,2,6], [1,7,3], [1,1,1]]
[[1,7,3],[1,1,1],[2,2,6]]

【讨论】:

  • 当列表的长度不同时,我认为这不起作用。
  • @dave4420:你完全正确,现在应该修复它(列表其余部分相同的较长列表现在大于较短列表)。很好的收获。
  • 您导入了 mconcat 而不是 mappend。现在流行用&lt;&gt;代替`mappend`
  • 但事实上,也许你真的是故意导入mconcat。因为这样你就有了写compareList 的更简单的方式,并且使用了更通用的类型:compareList :: Monoid c =&gt; (a -&gt; b -&gt; c) -&gt; [a] -&gt; [b] -&gt; c; compareList c xs ys = mconcat $ zipWith c xs ys
【解决方案2】:

要复制&lt; 的行为,您必须使您的xxx 函数成为类型类的一部分。这可能不值得。

请考虑为列表专门编写一个新版本的xxx

xxxl :: Integral i => [i] -> [i] -> Ordering
xxx1 [] [] = EQ
xxxl [] _ = LT
xxxl _ [] = GT
xxxl (l1:_) (l2:_) | odd l1    = LT
                   | otherwise = GT

您可能希望以其他方式处理空列表。这也说明了为什么您不能自动将您的 xxx 函数泛化到列表:将如何处理空列表?你必须以某种方式回答这个问题,而为列表编写一个新函数是最简单的方法。

您现在可以使用 xxxl 函数和 sortBy 对列表列表进行排序:sortBy xxx ...

【讨论】:

    猜你喜欢
    • 2013-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-10
    • 1970-01-01
    • 2015-02-09
    • 2011-07-09
    相关资源
    最近更新 更多