我有一个列表列表,以及一个返回包含最多项目的列表的函数:
extract ::[Plateau]->Plateau
extract(x:xs)
|x==maximumBy(compare `on` length)(x:xs)=x
|otherwise = extract(xs)
extract []=[""]
现在我需要一个函数来获取相同的[Plateau]
并返回一个删除了之前最大的新[Plateau]
:
prune::[Plateau]->[Plateau]
prune(x:xs)
|x < (maximumBy(compare `on` length)(x:xs)=x : prune (xs)
|x>=maximumBy(compare `on` length)(x:xs)=[]
prune [] = []
我还使用sortBy
调用prune以确保最大列表是最后一个:
(extract . prune) (sortBy(compare `on` length)(plateaus))
这开始正常工作。我的列表plateaus
看起来像:
plateaus = ["01000"], ["01010", "11010", "10010"] ["00101"], ["01101", "01001"]]
这里排序:
[["01000"], ["00101"], ["01101", "01001"], ["01010", "11010", "10010"]]
现在,我的函数prune返回
列表[["01000"], ["00101"]]
告诉我,出于某种原因Haskell认为
["01101", "01001"] >= ["01010", "11010", "10010"]
当我能清楚地看到2&gt; = 3不成立时。
为什么会这样?
答案 0 :(得分:8)
这样的事情可能是一个更简单的选择,也许是:
prune :: [Plateau] -> [Plateau]
prune s@(w:x:xs) = filter ( /= maxplateau ) s
where maxplateau = maximumBy (compare `on` length) s
prune _ = []
这依赖于Haskell的几个不错的部分。
第一个是模式匹配 - 您在问题中使用过这个问题,在上一个问题中 - 我在这里,我更进一步,要求一个包含至少两个元素的列表,w
和{ {1}}。这允许直通案例处理空条目和单条目列表情况,这应该(基于您提供的代码)导致相同的事情:空列表。
第二种是使用x
符号,AKA as patterns。我在回答你之前的问题时向你展示了这一点。虽然只是语法糖,而不是必需的,但它可以使代码更具可读性。
第三种是currying,有时称为“部分功能应用”。在我的例子中,我使用了Learn you a Haskell调用partial application of an infix function using sections(你应该阅读整个部分 - 非常具有形成性,能很好地解决Haskell语言的一个支柱(事实上,如果你真的喜欢或者我希望得到一个很好的初学者对Haskell的掌握,我会读到了解你的Haskell封面,因为它太棒了))。无论如何,这就是我在@
使用的内容;通常,中缀函数( /= maxplateau )
采用相同类型的两个参数,并返回/=
- 通过括在括号中并在一侧提供表达式,我已部分应用它。这会生成一个Bool
参数的函数,非常适合在Plateau
列表中提供过滤函数。
最后,在我的编辑中,我稍微更改了我的答案以使用Plateau
关键字。我这样做只是为了让部分应用更加清晰。我鼓励你在{了解你是一个哈斯克尔的where section中阅读更多关于where
的信息(你能告诉我有偏见吗?:^))
答案 1 :(得分:6)
列表比较是词典,而不是长度。所以你得到你看到的结果,因为“01101”&gt; =“01010”,这又是出于同样的原因 - 两个字符串的前两个字符是相等的,第一个字符的第三个字符大于第三个字符第二个。