简体   繁体   English

分开列表haskell的偶数和奇数元素

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM