【问题标题】:Haskell pair and unpair functionsHaskell 配对和取消配对功能
【发布时间】:2010-07-16 15:45:52
【问题描述】:

我写了以下两个函数。

pair :: [a] -> [(a, a)]
pair [] = []
pair [x] = []
pair (x1:x2:xs) = (x1, x2) : pair xs

unpair :: [(a, a)] -> [a]
unpair [] = []
unpair ((x1, x2):xs) = x1 : x2 : unpair xs

Pair 将采用成对的元素并将它们组成 2 元组。如果列表有奇数个元素,则丢弃最后一个。取消配对是配对的反面。

这些工作,但想知道是否有更简洁的方式来编写这些。

【问题讨论】:

  • 这可能有点冗长,但我会说与迄今为止的答案相比,它在清晰度方面胜出。 (无意冒犯这些作者。)
  • 我认为这里的要点是,列表上的 everyOther 函数会很有用,因为人们确实倾向于使用 zip 方法。 Hackage 上的 splits 包有 splitEvery 这将使这种解决方案更加明显。
  • 讨厌这么说,但对于我迄今为止看到的替代方案:我说的是简洁,而不是迟钝。 :(

标签: haskell coding-style tuples


【解决方案1】:

单行:

pair xs = map snd . filter fst . zip (iterate not True) $ zip xs (drop 1 xs)
unpair = concatMap (\(x,y) -> [x,y])

您还可以稍微缩写pair 的定义:

pair (x1:x2:xs) = (x1, x2) : pair xs
pair _ = []

【讨论】:

    【解决方案2】:

    它不再简洁,但为了清楚起见,我会使用 splitEvery from Data.List.Split for pair

    pair = map tuplify . filter ((>1) . length) . splitEvery 2
      where
        tuplify [x, y] = (x, y)
    

    这不是我的想法——最好只检查最后一个列表的长度。

    对于unpair,我会使用foldr 来避免显式递归:

    unpair = foldr (\(x, y) -> (x:) . (y:)) []
    

    这只是口味问题。

    【讨论】:

    • +1 支持我正在进行的推广使用 tuplify 名称的活动。
    • unpair = foldr (\\(x, y) -> ([x, y] ++)) [] 更好 imo。
    【解决方案3】:

    很多可能性。这些呢?

    unpair' = concatMap (\(x,y) -> [x,y])
    pair' xs = map snd . filter fst . zip (cycle [True, False]) $ zip xs (tail xs)
    pair'' xs = [(x,y) | (True,x,y) <- zip3 (cycle [True,False]) xs (tail xs)]
    

    pair 的两个版本应该是一样的。

    编辑:关于我上面的评论,可以使用 Hackage 的拆分包来编写:

    pair xs = map head . splitEvery 2 $ zip xs (tail xs)
    

    更接近想要的

    pair xs = everyOther $ zip xs (tail xs)
    

    但是,本着毫无意义的精神,我认为我们可能都应该同意写它,

    pair = map head . splitEvery 2 . (zip <$> id <*> tail)
    

    以确保混乱。

    【讨论】:

    • 带有列表理解的好版本。 +1。
    【解决方案4】:
    pair s = dropEven $ zip s (tail s)
         where dropEven s = map fst $ filter snd $ zip s (cycle [True, False])
    
    unpair = concatMap (\(a, b) -> [a, b])
    

    虽然我绝对更喜欢你对pair的定义。

    【讨论】:

    • 我们提出了几乎相同的解决方案 :-)
    【解决方案5】:

    这是view patterns的一个很好的用途:

    {-# LANGUAGE ViewPatterns #-}
    
    pair :: [a] -> [(a,a)]
    pair (splitAt 2 -> ([x,y],ys)) = (x,y) : pair ys
    pair _ = []
    
    unpair :: [(a,a)] -> [a]
    unpair = (>>= \(x,y) -> [x,y])
    

    【讨论】:

    • 我不认为pair (splitAt 2 -&gt; ([x,y],ys)) =pair (x:y:ys) = 更具可读性。
    • 但这不使用视图模式...:-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-23
    • 2014-04-20
    • 2021-12-15
    • 1970-01-01
    • 1970-01-01
    • 2021-11-16
    相关资源
    最近更新 更多