【问题标题】: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

标签: list sorting haskell minimum


【解决方案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。也许让它成为立方体,谁知道呢。
猜你喜欢
  • 2012-03-08
  • 2012-03-13
  • 1970-01-01
  • 1970-01-01
  • 2022-08-18
  • 2011-02-07
  • 2011-05-21
  • 2020-08-02
相关资源
最近更新 更多