[英]separate even and odd elements of list haskell
I am trying to separate elements of a list into to further lists, one for the odd and one for even numbers. 我正在尝试将列表的元素分成更多列表,一个用于奇数,一个用于偶数。
For Example, 例如,
input: [1,2,3,4,10]
output: ([2,4,10],[1,3])
sepList :: [Int]->([Int],[Int])
sepList [] = ([],[])
sepList (x:xs) | (x mod 2) ==0 = (([x],[]) ++ sepList xs)
| (x mod 2) /=0 = (([],[x]) ++ sepList xs)
| otherwise = ([],[])
It gives error on ...++ sepList xs
anyone could guide me here? 它在
...++ sepList xs
上给出错误,有人可以在这里指导我吗?
The operator ++
is used to concatenate 2 lists and neither of your arguments to ++
is a list, 运算符
++
用于连接2个列表,而++
的参数都不是列表,
([x],[]) ++ sepList xs
both ([x],[])
and sepList xs
are pairs of lists. ([x],[])
和sepList xs
都是列表对。 So what you want is to pattern match on sepList xs
eg using a let
binding, 因此,您想要在
sepList xs
上进行模式匹配,例如使用let
绑定,
let (ys,zs) = sepList xs in
and then return, 然后返回
(x:ys,zs)
You aren't concatenating two lists; 您没有串联两个列表; you want to add a single element to a list, selected from the tuple output of the recursive call.
您想要将一个元素添加到列表中,该列表是从递归调用的元组输出中选择的。 Don't use
(++)
; 不要使用
(++)
; use (:)
. 使用
(:)
。
sepList (x:xs) = let (evens, odds) = sepList xs
in if even x
then (x:evens, odds)
else (evens, x:odds)
More simply, though, sepList = partition even
. 不过,更简单地说,
sepList = partition even
。 ( partition
can be found in Data.List
.) (可以在
Data.List
找到partition
。)
There are two answers so far which suggest basically doing this by hand (by pattern-matching on the result of the recursive call), but there is actually an operator already defined for the types that you're working with that does exactly what you want! 到目前为止,有两个答案建议基本上是手动执行此操作(通过对递归调用的结果进行模式匹配),但是实际上已经为您使用的类型定义了一个运算符,它可以完全满足您的要求! Lists form a monoid with
(<>) = (++)
, but you don't have two lists: you have two pairs of lists. 列表以
(<>) = (++)
构成一个monoid,但是您没有两个列表:您有两对列表。 Happily, the type of pairs are also a monoid if each element of the pair is a monoid: (a,b) <> (c,d) = (a <> c, b <> d)
. 幸运的是,如果对中的每个元素都是一个对映体,则对的类型也是一个对映体:
(a,b) <> (c,d) = (a <> c, b <> d)
。 So, you can simply replace your ++
call with <>
, which will result in concatenating the corresponding lists in your pairs. 因此,您可以简单地用
<>
替换++
调用,这将导致连接成对的相应列表。
对于发烧友来说,遵循一行也可以将偶数和奇数分开。
sepList xs = (filter even xs , filter odd xs)
import Data.List
sepList :: [Int]->([Int],[Int])
sepList = partition even
sepList [1,2,3,4,10]
In this case i would use an accumulator
to create the tuple containing the two lists.In our case the accumulator
is ([],[])
. 在这种情况下,我将使用一个
accumulator
来创建包含两个列表的元组。在我们的示例中, accumulator
是([],[])
。
split::[Int]->([Int],[Int])
split ls= go ([],[]) ls where
go accu [] = accu
go (odd,even) (x:xs) | x `mod` 2==0 = go (x:odd,even) xs
| otherwise = go (odd, x:even) xs
As you can see the elements need to be reversed since we are pushing on top of our lists with the :
operator. 如您所见,由于我们使用
:
运算符将元素推到列表的顶部,因此需要反转元素。
I do not know if this is optimal but i would write it like this with reverse
: 我不知道这是否是最佳的,但我会用它写这样的
reverse
:
module Split where
split::[Int]->([Int],[Int])
split ls=let rev tupl=(reverse . fst $ tupl ,reverse .snd $ tupl) in
rev $ go ([],[]) ls where
go accu [] = accu
go (odd,even) (x:xs) | x `mod` 2==0 = go (x:odd,even) xs
| otherwise = go (odd, x:even) xs
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.