假设我有两个相同长度的列表A和B.我想在A中保留大于B中相应元素的元素。设A=[1,5,8], B=[2,4,9],
结果应为[5],因为1<2, 5>4, 8<9.
我想出了一个解决方案。让C=zip A B,
然后过滤C,最后通过取C中每个元素的fst得到结果。它不是那么优雅。有更简单的方法吗?
代码:
map fst (filter (\ x-> (fst x) > (snd x)) (zip a b))
答案 0 :(得分:4)
您描述的解决方案对我来说很好。
另一种不一定更好的选择:
import Data.Maybe
import Control.Monad
catMaybes $ zipWith (\a b -> guard (a>b) >> return a) list1 list2
根据monad comprehensions的贬值,这也应该起作用
{-# LANGUAGE MonadComprehensions #-}
[ a | ( a <- list1 | b <- list2 ), a > b ]
......但实际上却没有。很遗憾,因为我发现它非常优雅。 我想知道我是错了还是GHC错误。
答案 1 :(得分:1)
我不确定您的代码看起来如何,但以下功能对我来说非常优雅:
File "main.py", line 3
print num1, "is greater than", num2
^
IndentationError: expected an indented block
这种模式在Lisp社区中作为 decorate-process-undecorate 模式而众所周知。
答案 2 :(得分:1)
一种递归方法,不像其他方法那样优雅,这依赖于没有明确的压缩,我们在一次传递中得到结果,
greater :: Ord a => [a] -> [a] -> [a]
greater [] [] = []
greater (x:xs) (y:ys)
| x > y = x : greater xs ys
| otherwise = greater xs ys
答案 3 :(得分:1)
我正在从事类似的工作,作为一个新手,这是我想出的最好的方法:
filterGreaterThan xs ys = do (x,y) <- zip xs ys
guard (x > y)
return x
此解决方案比其他解决方案更容易推理。捐赠符号确实在这里闪耀。
答案 4 :(得分:0)
如果您想很好地概括这个想法,建议您参考mapMaybe
:
mapMaybe
:: (a -> Maybe b)
-> [a] -> [b]
将该想法应用于zipWith
会产生结果
zipWithMaybe
:: (a -> b -> Maybe c)
-> [a] -> [b] -> [c]
zipWithMaybe f xs ys =
[c | Just c <- zipWith f xs ys]
现在您可以编写函数了
keepGreater :: Ord a => [a] -> [a] -> [a]
keepGreater = zipWithMaybe $
\x y -> x <$ guard (x > y)
真的值得麻烦吗?对于列表,可能不是。但是事实证明,在Data.Map
的合并上下文中,类似的东西很有用。
答案 5 :(得分:0)
与@chi的列表一致解决方案非常相似:
concat $ zipWith (\a b -> last $ []:[[a] | a > b]) as bs