【问题标题】:Haskell: function to sort 1st element of 3 tuples lexicographicallyHaskell:按字典顺序对 3 个元组的第一个元素进行排序的函数
【发布时间】:2019-03-09 23:29:37
【问题描述】:

假设我们有一个电子表格 :: [(String,String,Int)] 包含 三元组 (name, user,mark) 其中 name 是学生的姓氏,用户 是他的用户名,mark 是学生第一个 CW 的结果。 编写一个按字典顺序对电子表格进行排序的函数 sortLastname 使用练习 2 中定义的高阶插入排序按名称。

我的练习 2 代码:

homerge :: Ord b => (a -> b) -> [a] -> [a] -> [a]
homerge _ xs [] = xs
homerge _ [] ys = ys
homerge fun (x:xs) (y:ys) | fun x < fun y = x : homerge fun xs (y:ys)
                          | otherwise = y : homerge fun (x:xs) ys`


hoMergeSort :: Ord b => (a -> b) -> [a] -> [a]
hoMergeSort _ [x] = [x]
hoMergeSort fun xs = homerge fun (hoMergeSort fun ys) (hoMergeSort fun ws)
                 where (ys,ws) = (take l xs, drop l xs)
                               where l = length xs `div` 2

我目前的尝试:

sortLastName [(x,y,z)] = hoMergeSort ( (x,_,_) (x',_,_) = x<x' ) [(x,y,z)]

我的问题是获得正确的函数来检查 3 元组的第一个元素是否小于下一个元素。

任何建议将不胜感激。

【问题讨论】:

  • 看来你在猜haskell的语法。我认为这个问题有点过于宽泛(所以不是家庭作业写作服务)。也许您可以将其简化为一个特定问题?例如,您对hoMergeSort 的第一个参数有疑问,那么为什么不删除问题的所有其他部分并询问( (x,_,_) (x',_,_) = x&lt;x' ):这应该有什么类型?你想让它做什么?您从编译器中得到了哪些错误?具体是什么让您对它们感到困惑?
  • 对不起,我以为我指定了。我的意思是,什么样的代码可以让我将元组的第一个元素与一个代替 ( (x,_,_) (x',_,_) = x&lt;x' ) 的函数进行比较
  • 写完练习2的解法,你看懂了吗?在继续后面的步骤之前,可能值得确保你理解它
  • 欢迎来到 StackOverflow @henahzurfdsa!我们通常为与作业相关的问题添加homework 标签,您可以编辑您的帖子以添加标签吗?当您使用它时,请不要犹豫,在您的评论中包含澄清(说您正在寻找( (x,_,_) (x',_,_) = x&lt;x' ) 的替代品)在您的帖子中。除此之外,在我看来,这是一个写得很好的问题——它展示了你的尝试并提出了明确的问题:)。

标签: haskell


【解决方案1】:

我们不要跑。让我们慢慢来:

-- sortLastName [(x,y,z)] = hoMergeSort ( (x,_,_) (x',_,_) = x<x' ) [(x,y,z)]
sortLastName xyzs = hoMergeSort fun xyzs
    where

让我们研究一下这个定义,

-- homerge fun (x:xs) (y:ys) | fun x < fun y = x : homerge fun xs (y:ys)

看,我们有fun xfun y 吗?哪个结果作为操作数进入&lt; 比较?

    fun (x,y,z) =  

我们希望将此处可用的哪些值作为操作数进入&lt; 比较?

                  .....

fun 不用于比较。 是由&lt; 在你的函数homerge 的源代码中完成的。 fun 函数用于提供要在该比较中使用的值

慢慢走,走远。


请注意,这不是字典顺序。这是按三元组的第 n 个字段排序,而与其他字段的值无关。字典顺序是相当的

(x,y,z) < (a,b,c) = x < a || x==a && (y < b || y==b && z < c)

【讨论】:

  • 您在最后一句中定义的顺序似乎是错误的。特别是,按照这个顺序,(1,2,3)
  • OP 正在寻找“按名称按字典顺序”排序,因此他们想要第一个字段 ("bar","zozo",9) &lt; ("foo","alfa",2) 的字典顺序,因为 "bar" &lt; "foo"。所以我认为它 is 是字典顺序(在投影上,而不是在整个元组上)。
  • @GeorgesDupéron 重新阅读这篇文章,我认为你是对的。幸运的是,&lt; 已经按照字典顺序对字符串进行了比较。
【解决方案2】:

语法

-- ( (x,_,_) (x',_,_) = x<x' )

不太有效。要创建匿名函数,请使用语法 \arg -&gt; result。如果您要编写上述内容,结果将是另一个返回 x&lt;x' 的函数:

-- \(x,_,_) -> ( \(x',_,_) -> x<x' )
-- i.e. without the parentheses:
-- \(x,_,_) -> \(x',_,_) -> x<x'

正如@WillNess 指出的那样,您已经在homerge 的定义中进行了比较fun x &lt; fun y

因此,fun 参数应该是从整个元组到您要比较的部分的投影。

\(x,_,_) -> x

那么整个 sortLastName 函数就是:

sortLastName xyzs = hoMergeSort (\(name,_,_) -> name) xyzs where

正如@WillNess 所建议的,您可以使用where 语法,这对于小型助手定义非常实用:

sortLastName xyzs = hoMergeSort fun xyzs where
  fun (name,_,_) = name

请注意,通过仅提供比较,您无法轻松颠倒顺序。如果name 字段是Num,则可以返回0-x,即\(x,_,_) -&gt; -x 以降序排序,但对于字符串,没有实际的方法可以做到这一点。因此,最好修改 hoMergeSort 使其接受与两个参数的比较,而不是期望单个参数的投影。

【讨论】:

    猜你喜欢
    • 2021-09-05
    • 2022-06-28
    • 2015-11-11
    • 2016-03-04
    • 2018-10-24
    • 2019-09-01
    • 2020-08-02
    • 1970-01-01
    相关资源
    最近更新 更多