Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List Haskell:使用列表的模式匹配_List_Haskell - Fatal编程技术网

List Haskell:使用列表的模式匹配

List Haskell:使用列表的模式匹配,list,haskell,List,Haskell,我试图创建一个函数,它接受一个列表,如果其中一个元素是负数,那么该列表中任何与它的正对应元素相等的元素都应该更改为0。例如,如果列表中有-2,那么该列表中的所有2都应该更改为0 你知道为什么它只适用于某些情况而不适用于其他情况吗?我不明白这是为什么,我已经看了好几遍了 changeToZero [] = [] changeToZero [x] = [x] changeToZero (x:zs:y:ws) | (x < 0) && ((-1)*(x) == y) = x :

我试图创建一个函数,它接受一个列表,如果其中一个元素是负数,那么该列表中任何与它的正对应元素相等的元素都应该更改为0。例如,如果列表中有-2,那么该列表中的所有2都应该更改为0

你知道为什么它只适用于某些情况而不适用于其他情况吗?我不明白这是为什么,我已经看了好几遍了

changeToZero [] = []
changeToZero [x] = [x]
changeToZero (x:zs:y:ws) | (x < 0) && ((-1)*(x) == y) = x : zs : 0 : changeToZero ws
changeToZero (x:xs) = x : changeToZero xs

changeToZero [-1,1,-2,2,-3,3]
-- [-1,1,-2,2,-3,3]

changeToZero [-2,1,2,3]
-- [-2,1,0,3]

changeToZero [-2,1,2,3,2]
-- [-2,1,0,3,2]

changeToZero [1,-2,2,2,1]
-- [1,-2,2,0,1]
changeToZero[]=[]
更改为零[x]=[x]
changeToZero(x:zs:y:ws)|(x<0)和&(-1)*(x)==y)=x:zs:0:changeToZero-ws
changeToZero(x:xs)=x:changeToZero-xs
更改为零[-1,1,-2,2,-3,3]
-- [-1,1,-2,2,-3,3]
更改为零[-2,1,2,3]
-- [-2,1,0,3]
更改为零[-2,1,2,3,2]
-- [-2,1,0,3,2]
更改为零[1,-2,2,2,1]
-- [1,-2,2,0,1]

我认为列表理解在这里更清晰、更容易获得

changeToZero xs = [if x > 0 && (-x) `elem` xs then 0 else x | x <- xs]

我认为列表理解在这里更清晰、更容易理解

changeToZero xs = [if x > 0 && (-x) `elem` xs then 0 else x | x <- xs]

你实际上不记得在列表中找到了哪些负面符号

import qualified Data.Set as S

changeToZero :: [Int] -> [Int]
changeToZero [] = []
changeToZero xs = reverse . snd $ foldl f (S.empty,[]) xs
  where
    f (negs,res) x | x < 0 = (S.insert (-x) negs, x:res)
                   | S.member x negs = (negs,0:res)
                   | otherwise = (negs,x:res)
导入符合条件的数据。设置为S
更改为零::[Int]->[Int]
更改为零[]=[]
changeToZero xs=反向。snd$foldl f(S.empty,[])xs
哪里
f(负的,res)x | x<0=(插入(-x)负的,x:res)
|S.member x negs=(negs,0:res)
|否则=(负,x:res)

您实际上不记得在列表中找到了哪些负面符号

import qualified Data.Set as S

changeToZero :: [Int] -> [Int]
changeToZero [] = []
changeToZero xs = reverse . snd $ foldl f (S.empty,[]) xs
  where
    f (negs,res) x | x < 0 = (S.insert (-x) negs, x:res)
                   | S.member x negs = (negs,0:res)
                   | otherwise = (negs,x:res)
导入符合条件的数据。设置为S
更改为零::[Int]->[Int]
更改为零[]=[]
changeToZero xs=反向。snd$foldl f(S.empty,[])xs
哪里
f(负的,res)x | x<0=(插入(-x)负的,x:res)
|S.member x negs=(negs,0:res)
|否则=(负,x:res)

好吧,根据@jdevelop的答案,如果为了计数,负数必须出现在正数之前,那么您可以通过对输入进行单次传递来生成结果,而无需反转:

import qualified Data.Set as S
import Control.Monad.State

changeToZero :: [Int] -> [Int]
changeToZero xs = evalState (mapM f xs) S.empty where
  f x | x < 0     = modify (S.insert (-x)) >> return x
      | otherwise = gets (S.member x) >>= \hasNeg -> return $ if hasNeg then 0 else x
其他解决方案将失败的地方

**编辑**

这是同样的事情,但是没有
状态
单子,这使得它更容易理解:

changeToZero' :: [Int] -> [Int]
changeToZero' = go S.empty where
  go _ [] = []
  go s (x:xs) | x < 0        = x : go (S.insert (-x) s) xs
              | S.member x s = 0 : go s xs
              | otherwise    = x : go s xs
changeToZero'::[Int]->[Int]
changeToZero'=去S.空在哪里
go[]=[]
go s(x:xs)| x<0=x:go(s.insert(-x)s)xs
|S.member x S=0:go S xs
|否则=x:go s xs

好吧,根据@jdevelop的答案,如果为了计数,负数必须出现在正数之前,那么您可以通过对输入进行单次传递来生成结果,而无需反转:

import qualified Data.Set as S
import Control.Monad.State

changeToZero :: [Int] -> [Int]
changeToZero xs = evalState (mapM f xs) S.empty where
  f x | x < 0     = modify (S.insert (-x)) >> return x
      | otherwise = gets (S.member x) >>= \hasNeg -> return $ if hasNeg then 0 else x
其他解决方案将失败的地方

**编辑**

这是同样的事情,但是没有
状态
单子,这使得它更容易理解:

changeToZero' :: [Int] -> [Int]
changeToZero' = go S.empty where
  go _ [] = []
  go s (x:xs) | x < 0        = x : go (S.insert (-x) s) xs
              | S.member x s = 0 : go s xs
              | otherwise    = x : go s xs
changeToZero'::[Int]->[Int]
changeToZero'=去S.空在哪里
go[]=[]
go s(x:xs)| x<0=x:go(s.insert(-x)s)xs
|S.member x S=0:go S xs
|否则=x:go s xs

表达式
x:zs:y:ws
相当于
[x,zs,y]++ws
。因此,
zs
将始终是列表中的单个元素;它永远不会是多个元素(或者没有元素)。如果我想让zs成为多个元素,x:zs:y会让它被认为是多个元素,而不是单个元素吗?对不起,我正在尽我所能地学习,因为我是初学者!恐怕不行。在表达式(或模式)
a:b
中,
a
始终是单个元素,
b
始终是列表;表达式
a:b
相当于
[a]++b
。由于
是右关联的,这意味着在诸如
a:b:c:d
之类的表达式(或模式)中,最右边的变量是“列表的其余部分”,其他变量是单个元素。表达式
x:zs:y:ws
相当于
[x,zs,y]++ws
。因此,
zs
将始终是列表中的单个元素;它永远不会是多个元素(或者没有元素)。如果我想让zs成为多个元素,x:zs:y会让它被认为是多个元素,而不是单个元素吗?对不起,我正在尽我所能地学习,因为我是初学者!恐怕不行。在表达式(或模式)
a:b
中,
a
始终是单个元素,
b
始终是列表;表达式
a:b
相当于
[a]++b
。由于
是右关联的,这意味着在表达式(或模式)中,例如
a:b:c:d
,最右边的变量是“列表的其余部分”,其他变量是单个元素。不必要的复杂,查看优雅的基于列表理解的hammar解决方案,它仍然更有效,因为使用列表理解版本,列表会被评估2次。还是没有理由投反对票。谢谢你的回复!我宁愿只使用Data.List,但这也行!我对你的答案投了赞成票:)只有当负数出现在正数之前,这才有效。根据问题的第一段,我不确定这是否是OP想要的。我承认OP的代码建议后续值应为零,但这可能是错误的。不必要的复杂,请参阅优雅的基于列表理解的hammar解决方案它仍然更有效,因为使用列表理解版本,列表会被计算2次。还是没有理由投反对票。谢谢你的回复!我宁愿只使用Data.List,但这也行!我对你的答案投了赞成票:)只有当负数出现在正数之前,这才有效。根据问题的第一段,我不确定这是否是OP想要的。我承认OP的代码建议后续值应为零,但这可能是错误的。谢谢!我不知道你可以用if/else子句来理解列表。(我是个初学者,就像你说的,哈哈):)