【问题标题】:Haskell - Merge Sort, sorting words and numbersHaskell - 合并排序,对单词和数字进行排序
【发布时间】:2011-09-26 11:13:54
【问题描述】:

我在 Haskell 中编写了一个合并排序,它在使用数字时有效,但不适用于单词,我认为它会。使用单词和字母时,我只会得到“不在范围内”。我做错了什么?

这是我的代码:

merge :: Ord a => [a] -> [a] -> [a]
merge [] ys = ys
merge xs [] = xs
merge (x:xs) (y:ys)
    | x <= y = x : merge xs (y:ys)
    | otherwise = y : merge (x:xs) ys

mergeSort :: Ord a => [a] -> [a]
mergeSort [] = []
mergeSort [x] = [x]
mergeSort xs
    = merge (mergeSort top) (mergeSort bottom)
    where
    (top, bottom) = splitAt (length xs `div` 2) xs

【问题讨论】:

  • 这适用于字符串,f.e. mergeSort ["banana", "candy", "apple"]
  • 您的代码看起来不错。查看确切的输入和完整的错误消息可能会有所帮助。 something 不在范围内并不是很有帮助...

标签: haskell mergesort


【解决方案1】:

你是这样输入的吗?

[this,is,an,example,sentence]

语法不正确。如果你想输入一个文字字符串,你必须把它用双引号括起来("):

["this","is","an","example","sentence"]

如果这不是您的错误,请随意忽略此答案。

【讨论】:

  • 可以肯定的是,语法是正确的,这就是他得到“不在范围内”错误而不是语法错误的原因。
  • @Ingo 当然语法在形式上是正确的,但这不是 OP 想要的。
【解决方案2】:

您的代码运行良好。

但是我建议一次性拆分列表,而不使用length。当然,顺序在这里并不重要,只是我们有两个大小大致相同的列表。你可以这样做:

splitList [] = ([],[])
splitList [x] = ([x],[])
splitList (x:y:zs) = let (xs,ys) = splitList zs in (x:xs, y:ys)  

...或尾递归...

splitList zs = go zs [] [] where
   go [] xs ys = (xs, ys)
   go [x] xs ys = (x:xs, ys)
   go (x:y:zs) xs ys = go zs (x:xs) (y:ys)    

...或使用索引...

splitList xs = (go even, go odd) where
   go f = map snd $ filter (f.fst) $ indexed
   indexed = zip [0..] xs

...或使用折叠...

import Data.List

splitList zs = snd $ foldl' go (True,([],[])) zs where
   go (True,(xs,ys)) x = (False,(x:xs,ys))   
   go (False,(xs,ys)) x = (True,(xs,x:ys)) 

【讨论】:

  • 正如我在 #haskell 上向我指出的那样,当我提出类似的解决方案时,需要权衡:使用此解决方案时,排序不稳定。
  • 好吧,那就计算一次原始列表的长度。然后将您发送给助手的列表的长度传递给助手,这可以通过简单的除以 2 操作来完成。我个人认为将原始列表的每个元素映射到单例列表的方法很酷。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-14
  • 1970-01-01
相关资源
最近更新 更多