【问题标题】:Rearrange/sort list by largest, smallest, second largest, second smallest etc按最大、最小、第二大、第二小等重新排列/排序列表
【发布时间】:2019-03-11 17:00:21
【问题描述】:

给定一个整数数组,我如何对它们进行排序:最大-最小-第二大-第二小?

我正在尝试: - 按升序和降序复制和排序数组 - 通过挑选如上所述的每个数组的头部来创建排序数组

我不熟悉 Haskell 编程,但这就是我所做的

sort :: [Int] -> [Int]
sort [] = []
sort (x:xs) = sort smaller ++ [x] ++ sort larger
  where
    smaller = filter (<= x) xs
    larger = filter (> x) xs

wave :: [Int] -> [Int]
wave [] = []
wave [x] = [x]
wave (x:xs) = if length (x:xs)>1 
    then :
        ascending = sort (x:xs)
        descending = reverse (ascending)
        iterator = length(x:xs)
        if iterator > 0 && (length(ascending)==0 || length(descending)==0)
            then do wave(x:xs) = head(descending) + head(ascending)
                tail(descending)
                tail(ascending)

提前感谢您的帮助

【问题讨论】:

  • then : 是错误的语法。 : 不属于那里。如果您有多个定义,可以将它们放在一个let 中,如let { a = ... ; b = ... ; c = ... } in ...。

标签: list sorting haskell


【解决方案1】:

frontEndSort 使用列表xs,它按降序对其元素进行排序。接下来,将xs 中的每个元素与同一列表中的元素配对,但按升序排列。将每一对转换为列表,然后展平整个列表。最后,我们采用与xs 中一样多的元素。

frontEndSort :: [Int] -> [Int] 
frontEndSort xs = take (length xs) $ do
    (x, y) <- zip <$> sortBy (comparing Down) <*> sort $ xs
    [x, y]

【讨论】:

  • 不错的解决方案。比我建议的快 4 倍。只有一个建议sortBy (comparing Down) 可以用sortOn Down 代替
【解决方案2】:

braid 函数逐个插入两个列表元素。我们接下来将braid 应用于按升序和降序排序的列表。最后,由于我们最终会复制原始列表,因此我们只取原始列表的长度。

braid :: [Int] -> [Int] -> [Int]    
braid []     as     = as
braid ds     []     = ds
braid (d:ds) (a:as) = d:a:braid ds as

wave :: [Int] -> [Int]
wave xs = take (length xs) braided 
  where asc  = sort xs
        desc = reverse asc
        braided = braid desc asc

基准编辑:

尽管我认为我的实现对于 haskell 初学者来说更容易理解,但我不得不说,在将我的解决方案与 ƛƛƛ 的解决方案进行对比后,我的解决方案比他/她慢 4 到 7 倍。

对于十万长度的列表:

  • 我的:211 毫秒
  • ƛƛƛ 的:53 毫秒

对于一百万长度的列表:

  • 我的:3.8 秒
  • ƛƛƛ 的:547 毫秒

编辑二:不要使用reverse

将desc = reverse asc 替换为desc = sortOn Down xs 会产生与ƛƛƛ 的应用解决方案和意愿理解列表实施相同的速度程序。

【讨论】:

  • 试试take (length xs) (braid (reverse $ sort xs) (sort xs))。我想知道它是否可以更快。 (当然它仍然会比另一个慢,因为它直接产生反向列表)。
  • 问题实际上是reverse $ sort xs,将其替换为sortOn Down 会产生与其他解决方案相同的速度代码。没想到反转这么慢
  • @ƛƛƛ 标准库
【解决方案3】:

另一种使用压缩方式:

import Data.Ord

frontEndSort :: [Int] -> [Int] 
frontEndSort xs =
    zipWith (flip const) xs
       ( concat . getZipList . traverse ZipList
                $ [sortBy (comparing Down) xs, sort xs] )

这里是traverse ZipList :: [[b]] -&gt; ZipList [b],所以它已经将这些对生成为列表,而不是元组。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-19
    • 2016-11-07
    • 1970-01-01
    • 2021-12-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多