2010-09-14 126 views
3

我不能使用高阶函数。我看不出如何做到这一点。我对哈斯克尔很新。它也必须是递归的。Haskell:将偶数和奇数元素分解为元组

split :: [Int] -> ([Int],[Int]) 
split xs = 

我给了这个开始。我真的不知道从哪里开始解决这个问题。

例子:

split [] 
([],[]) 

split [1] 
([1],[]) 

split [1,2,3,4,5,6,7,8,9,10] 
([1,3,5,7,9],[2,4,6,8,10]) 

任何帮助,将不胜感激。

编辑:它的偶数和奇数位置。

所以

分裂[3,6,8,9,10]将 ([3,8,10],[6,9])

行,所以我想出了这个。它不漂亮,但它似乎工作正常。

split :: [Int] -> ([Int],[Int]) 
split [] = ([],[]) 
split [xs] = ([xs],[]) 
split xs = (oddlist xs, evenlist xs) 

oddlist :: [Int] -> ([Int]) 
oddlist xs | length xs <= 2 = [head(xs)] 
      | otherwise = [head(xs)] ++ oddlist(tail(tail(xs))) 

evenlist :: [Int] -> ([Int]) 
evenlist xs | length xs <= 3 = [head(tail(xs))] 
      | otherwise = [head(tail(xs))] ++ evenlist(tail(tail(xs))) 
+3

你的例子是有点暧昧,你的意思是,即使在本身是偶数或奇数元素和奇数位或整数?一个更好的例子可能是:'split [1,3,2,5,8]''>([1,3,5],[2,8])' – 2010-09-14 09:53:47

+0

哦,对不起,偶数和奇数位置的元素。 – Matt 2010-09-14 10:18:42

+0

@Tom嘿谢谢。没有注意到。 – Matt 2010-09-14 10:44:07

回答

16
split [] = ([], []) 
split [x] = ([x], []) 
split (x:y:xs) = (x:xp, y:yp) where (xp, yp) = split xs 
+0

您的签名稍微偏离了... – 2010-09-14 09:52:54

+0

@Konrad:我不知道您的意思。两个'???'不一样,我忽略了2个基本情况。 – kennytm 2010-09-14 09:59:43

+0

忘了它......我显然与Haskell联系太久了。请参阅我的原始答案:丢失列表构造函数周围的括号。 – 2010-09-14 10:09:37

3

如果你不能使用更高次序列表功能,您的选择是基本上使用递归。

的例子已经给你需要迎合情况:

-- Base case: 
split [] = … 

-- Recurrence: 
split (x : xs) = (do something with x) … (split xs) … 
+0

请注意,@ Kenny和我的解决方案解决了不同的问题。由于@Tom在您的问题下面评论过,由于您的示例不明确,因此不清楚这两种解决方案中的哪一种适合您的确切问题。 – 2010-09-14 10:17:31

2

既然你已经把你的解决方案了,现在,这是我将如何实现它:

split xs = (everyother 0 xs, everyother 1 xs) 
     where everyother _ []  = [] 
      everyother 1 (x:xs) = everyother 0 xs 
      everyother 0 (x:xs) = x : (everyother 1 xs) 

这意味着列表中的第一项是项目0.

+0

是的,那很好。有趣的想法。 – Matt 2010-09-14 11:40:05

1

我认为这与Get every Nth element有关。

无论如何,这是我会做什么:

ghci> let split ys = let skip xs = case xs of { [] -> [] ; [x] -> [x] ; (x:_:xs') -> x : skip xs' } in (skip ys, skip . drop 1 $ ys) 
ghci> split [1..10] 
([1,3,5,7,9],[2,4,6,8,10]) 

还是很好的格式化的:

split xs = (skip xs, skip . drop 1 $ xs) 
    where 
    skip [] = [] 
    skip [x] = [x] 
    skip (x:_:xs') = x : skip xs' 
2

如果你放松了“没有高阶函数”的限制,你可以像下面这样做:

split :: [a] -> ([a],[a]) 
split = foldr (\x ~(y2,y1) -> (x:y1, y2)) ([],[]) 

注意~使模式匹配懒惰,所以split可以根据需求产生结果,而不需要首先检查整个列表。

您可以通过展开foldr重新实行限制:

split :: [a] -> ([a],[a]) 
split [] = ([],[]) 
split (x : xs) = (x : y1, y2) 
    where 
    (y2, y1) = split xs 
+0

我修复了交换结果,并以预期的方式让事情变得懒惰。 – dfeuer 2016-03-17 17:17:03

相关问题