【问题标题】:How would you use map on a list of tuples that contains a list of tuples?您将如何在包含元组列表的元组列表上使用 map?
【发布时间】:2021-06-05 20:47:06
【问题描述】:

我在这里有一个具有以下结构的列表:

list = [((1,1),[("A", 1), ("D", 4), ("E", 5)]), ((2,2),[("B", 2)]), ((3,3),[("C",3)])]

我想输出一个具有以下结构的列表(也就是将每个子列表的每个第二个值的值相加,例如 (1+4+5) = 10

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

我不确定如何通过使用 map 甚至过滤器来获得该结构,而我得到的最接近的是:

map snd (concat (map snd list)) 

产生[1,4,5,2,3]

我将如何实现这种结构?

【问题讨论】:

    标签: list haskell functional-programming tuples


    【解决方案1】:

    如果您不介意map,您可以在此处使用列表理解:

    list = [((1,1),[("A",1),("D",4),("E",5)]),((2,2),[("B",2)]),((3,3),[("C",3)])]
    [(fst x, sum [snd y | y <- (snd x) ]) | x <- list]
    

    返回

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

    【讨论】:

    • 列表理解是一个不错的选择,但是您应该模式匹配fstsnd
    【解决方案2】:

    首先,写出类型:

    have :: [((Int,Int), [(String,Int)])]
    have = [ ((1,1),[("A", 1), ("D", 4), ("E", 5)]), ... ]
    
    want :: [((Int,Int), Int)]
    

    显然,(Int,Int) 在这里并不重要,String 也不是。所以我们的转换函数可以是

    give :: [(a, [(b, Int)])] -> [(a, Int)]
    

    此外,a 只是按原样传递,所以有趣的部分将是 [(b, Int)] -&gt; Int。为此,您首先需要扔掉bs

    Prelude> map snd [("A", 1), ("D", 4), ("E", 5)]
    [1,4,5]
    

    并对结果求和(组合!)

    Prelude> sum . map snd $ [("A", 1), ("D", 4), ("E", 5)]
    10
    

    所以sum . map snd 是您需要应用于外部元组列表中每个 RHS 的函数。

    您如何仅在 RHS 上实际使用它?好吧,一种方法是写一个 lambda

       \(x,y) -> (x, f y)
    

    ...但实际上有一个标准组合器,称为second

    second :: (b -> c) -> (d,b) -> (d,c)
    

    (对元组的snd 元素进行操作,对其应用函数,将其放回元组中)。

    Prelude Control.Arrow> second (sum . map snd) (346, [("A", 1), ("D", 4), ("E", 5)])
    (346,10)
    

    剩下要做的就是将整个内容映射到外部列表:

    Prelude Control.Arrow> map (second $ sum . map snd) [((1,1),[("A", 1), ("D", 4), ("E", 5)]), ((2,2),[("B", 2)]), ((3,3),[("C",3)])]
    [((1,1),10),((2,2),2),((3,3),3)]
    

    或者作为一个定义

    give :: Num c => [(a, [(b, c)])] -> [(a, c)]
    give = map . second $ sum . map snd
    

    如果您查看文档,您会发现second 实际上比这更通用:它不仅可以用于函数,还可以用于通用箭头~&gt;,即second :: Arrow (~&gt;) =&gt; (b ~&gt; c) -&gt; ((d,b)~&gt;(d,c))。如果这让您感到困惑,请不要担心……在大多数应用程序中,箭头只是普通功能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-28
      • 1970-01-01
      • 2016-06-27
      • 1970-01-01
      • 2020-12-25
      • 1970-01-01
      • 2019-10-20
      • 2018-06-15
      相关资源
      最近更新 更多