HASKELL-按最大,最小,第二大,第二小等重新排列/排序列表

时间:2018-10-06 10:48:19

标签: arrays list sorting haskell integer

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

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

我对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)

在此先感谢您的帮助

3 个答案:

答案 0 :(得分:5)

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

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

答案 1 :(得分: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毫秒
  • ƛƛƛ's:53毫秒

一百万个长度列表:

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

编辑二:不要使用reverse

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

答案 2 :(得分:1)

另一种使用压缩的方式:

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]] -> ZipList [b]已将其生成为列表而不是元组。