按元组的第二个元素对元组列表进行排序,无需高阶函数或递归

Posted

技术标签:

【中文标题】按元组的第二个元素对元组列表进行排序,无需高阶函数或递归【英文标题】:Sort a list of tuples by their second element without higher order functions or recursion 【发布时间】:2021-03-14 09:38:38 【问题描述】:

我有一个 (String, Int) 对的列表,我正在努力弄清楚如何按 snd 字段 (Int) 对列表进行排序。我不允许使用高阶函数或递归,这使得它变得更加困难。

例如,我有

[("aaaaa", 5),("bghdfe", 6),("dddr",4)] 

并想将其分类为

 [("dddr",4),("aaaaa", 5),("bghdfe", 6)].

编辑: 我知道没有高阶函数可能无法进行排序,我真正需要的是找到具有最小长度的元素(snd 字段),所以有没有办法找到最小数字然后取 @ 987654327@ 该索引处列表元素的字段?如果这种方式效果更好,我不确定如何找到该最小数字的索引。

【问题讨论】:

最小长度是多少? 您实际上可以使用什么?如果没有递归和高阶函数,它看起来是不可能的,除非有一些允许的方式来隐式调用 HO 函数。例如,列表推导可以有效地替换mapfilterconcatMapdo-notation 也是如此。是否允许?最重要的是,是否允许库 sort 函数? 每个Int都是字符串的长度,所以最小的int = 最小长度——我需要在一个字符串列表中找到最小的字符串 '使用基本函数、列表推导和库函数,但不使用递归' - 不允许排序 你可能不会使用minimumByfoldlsort 【参考方案1】:

这项任务似乎是不可能的,因为你不能在 Haskell 中编写没有递归的排序。这意味着,您必须使用sort,通常类似于sortBy compare,因此您拥有它。

但是如果您被允许使用sort,您可以通过首先反转所有元组、对结果列表进行排序并再次反转结果中的元组来实现。这应该可以在一些嵌套列表理解中完成,因此技术上不需要更高阶的函数。


在您提供更多详细信息后,我会这样做

homework list = snd (minimum [ (s,f) | (f,s) <- list ])

【讨论】:

谢谢,我认为反转元组列表并这样做会更复杂,但实际上更优雅 - 这完美解决了我的问题 minimum [(2,10),(2,2)] => (2,2) 但我们可能应该返回第一个,就像minimumBy (comparing fst) 那样。 IOW 对于[("bbb", 3), ("aaa", 3)] 的输入,您的函数返回"aaa",我希望"bbb" 作为返回值。 (虽然不清楚):) @WillNess 你可能是对的,但任务并不完全清楚。例如它说("aaa", 5)但5不是"aaa"的长度 仍然,使用minimum 是一个不错的发现。 minimumBy 将使用 HOF,但那样,不是。 :)【参考方案2】:

如果没有高阶函数或递归,从技术上讲,您剩下的就是列表推导。因此我们定义

-- sortBy (comparing snd) >>> take 1 >>> listToMaybe >>> fmap fst
--  ~= minimumBy (comparing snd) >>> fst
foo :: Ord b => [(a,b)] -> Maybe a
foo xs = case [ a | (a,b) <- xs
                  , null [ () | (_c,d) <- xs, d < b]]
         of (a:_) -> Just a
            []    -> Nothing

【讨论】:

我相信没有比这更复杂的完整解决方案了,所以任务分配教授一定是虐待狂或想明确递归和 HOF 的重要性。 顺便说一句,我相信即使sort 也可以用这种折磨人的方式来写,有很多很多的 LC。也许让它成为立方体,谁知道呢。

以上是关于按元组的第二个元素对元组列表进行排序,无需高阶函数或递归的主要内容,如果未能解决你的问题,请参考以下文章

根据元组的值,以不同的顺序对元组列表进行排序。

如何按两个元素对元组列表进行排序?

python 使用 sorted 对 列表嵌套元组的数据进行排序

按第二个值对元组列表进行排序,reverse=True,然后按 key,reverse=False

如何将元组的所有第一个元素与同一元组中相应的第二个元素进行比较

将 char 添加到列表中的每个元组的第二个元素