【问题标题】:Concatenating 2nd element of a tuple in a list in Haskell在 Haskell 的列表中连接元组的第二个元素
【发布时间】:2016-07-17 23:04:53
【问题描述】:

我有一个这样的列表:

[(1,[2]), (1,[3]), (1,[4]), (2,[1]), (2,[2]), (3,[1])]

我想要的是一个从列表中的第一个元素开始的函数,如果它在列表中找到具有相似元组 (fst) 的任何其他元素,那么它将找到的元素的 (snd) 连接到(snd) 第一个元素。在上面显示的示例中,最终结果将是以下列表:

[(1,[2,3,4]), (2,[1,2]), (3,[1])]

我尝试了很多选项,但都没有成功。有什么建议?

谢谢

【问题讨论】:

  • 你试过什么?您可能想使用Data.List.groupByData.Function.on 来玩groupBy ((==) `on ` fst)
  • 谢谢,但没有给出我想要的结果。运行您建议的函数在以下列表上方的同一列表中给了我:[[(1,[2]),(1,[3]),(1,[4])],[(2,[1] ),(2,[2])],[(3,[1])]] 而我想要的是: [(1,[2,3,4]), (1,[1,2]), ( 3,[1])]
  • 这个想法显然是你从那里开始,看看你是否可以自己完成它......但很遗憾你在下面有 2 个剧透;)
  • 呵呵。你说的对。谢谢卡斯滕

标签: haskell tuples concatenation


【解决方案1】:

注意groupBy如果相同值的键不连续,则不会分组。例如:

\> groupBy (==) [1, 2, 1]
[[1],[2],[1]]

因此,您需要确保传入一个排序列表。 另一种方法是使用Data.Map 和右折叠:

import Data.Map (empty, alter, toList)

fun :: (Foldable t, Ord k) => t (k, [a]) -> [(k, [a])]
fun = toList . foldr go empty
    where
    go (k, x) acc  = alter (inc x) k acc
    inc x Nothing  = Just x
    inc x (Just y) = Just (x ++ y)

无论列表是否排序,它都将起作用:

\> fun [(1,[2]), (1,[3]), (1,[4]), (2,[1]), (2,[2]), (3,[1])]
[(1,[2,3,4]),(2,[1,2]),(3,[1])]

\> fun [(3,[1]), (1,[2]), (2,[1]), (1,[3]), (2,[2]), (1,[4])]
[(1,[2,3,4]),(2,[1,2]),(3,[1])]

【讨论】:

    【解决方案2】:
    import Data.List (groupBy)
    import Data.Function (on)
    import Control.Arrow ((***))
    
    f  = map ((head *** concat) . unzip) . groupBy ((==) `on` fst)
    

    .

    > let l =  [(1,[2]), (1,[3]), (1,[4]), (2,[1]), (2,[2]), (3,[1])]
    
    > groupBy ((==) `on` fst) l
    [[(1,[2]),(1,[3]),(1,[4])],[(2,[1]),(2,[2])],[(3,[1])]]
    
    > map unzip $ groupBy ((==) `on` fst) l
    [([1,1,1],[[2],[3],[4]]),([2,2],[[1],[2]]),([3],[[1]])]
    

    您可以使用 Control.Arrow 中的 (***) 来操作元组

    > (pred *** succ) (4,5)
    (3,6)
    
    > let f  = map ((head *** concat) . unzip) . groupBy ((==) `on` fst) 
    > f l
    [(1,[2,3,4]),(2,[1,2]),(3,[1])]
    

    【讨论】:

    • 谢谢。这实际上解决了我的原始结构,它具有签名 [(Int,Int,Int),[Int])。当我提出这个问题时,我试图提出一个相当简单的结构。
    【解决方案3】:
    Prelude> :m + Data.Function Data.List    
    Prelude> let xs = [(1,[2]), (1,[3]), (1,[4]), (2,[1]), (2,[2]), (3,[1])]
    Prelude> map (\lst -> (fst $ head lst, concat $ map snd lst)) (groupBy ((==) `on` fst) xs)
    [(1,[2,3,4]),(2,[1,2]),(3,[1])]
    

    【讨论】:

    • 也谢谢。它也适用于我原来的结构。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-29
    • 1970-01-01
    • 2020-02-28
    • 2015-08-18
    相关资源
    最近更新 更多