【问题标题】:Haskell: split even and odd elements into tupleHaskell:将偶数和奇数元素拆分为元组
【发布时间】:2010-09-14 09:47:05
【问题描述】:

我不能使用高阶函数。我只是无法弄清楚如何做到这一点。我对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)))

【问题讨论】:

  • 你的例子有点模棱两可,你是指偶数和奇数位置的元素,还是本身是偶数或奇数的整数?一个更好的例子可能是:split [1,3,2,5,8] ~> ([1,3,5], [2,8])
  • 哦,是的,抱歉,元素在偶数和奇数位置。
  • @Tom 嘿,谢谢。没注意到。

标签: haskell


【解决方案1】:
split [] = ([], [])
split [x] = ([x], [])
split (x:y:xs) = (x:xp, y:yp) where (xp, yp) = split xs

【讨论】:

  • 你的签名有点不对……
  • @Konrad:我不明白你的意思。两个???不一样,我忽略了2个基本情况。
  • 算了吧……我显然与 Haskell 脱节太久了。请参阅我的原始答案:列表构造函数周围缺少括号。
  • @Konrad:是的,采用单个参数的函数永远不会被柯里化;-)
【解决方案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

【讨论】:

  • 我修复了交换的结果,并以预期的方式让事情变得懒惰。
【解决方案3】:

如果你不允许使用高阶列表函数,你的选择基本上是使用递归。

示例已经给出了您需要满足的情况:

-- Base case:
split [] = …

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

【讨论】:

  • 请注意,@Kenny 和我的解决方案解决了不同的问题。正如@Tom 在您的问题下方评论的那样,由于您的示例模棱两可,因此尚不清楚这两种解决方案中的哪一种适合您的确切问题。
【解决方案4】:

既然您现在提出了解决方案,我将采用以下方式实施它:

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 项。

【讨论】:

  • 是的,很好。有趣的想法。
【解决方案5】:

我认为它与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'

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-01-26
    • 1970-01-01
    • 2021-07-18
    • 1970-01-01
    • 2014-06-28
    • 1970-01-01
    • 2017-11-06
    相关资源
    最近更新 更多