2010-09-14 139 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

相關問題