按元组的第二个元素对元组列表进行排序,无需高阶函数或递归
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 函数。例如,列表推导可以有效地替换map
、filter
、concatMap
。 do
-notation 也是如此。是否允许?最重要的是,是否允许库 sort
函数?
每个Int都是字符串的长度,所以最小的int = 最小长度——我需要在一个字符串列表中找到最小的字符串
'使用基本函数、列表推导和库函数,但不使用递归' - 不允许排序
你可能不会使用minimumBy
或foldl
或sort
?
【参考方案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