【问题标题】:Haskell: How do I combine a list of list of tuples using foldr?Haskell:如何使用 foldr 组合元组列表?
【发布时间】:2018-09-23 01:21:42
【问题描述】:

我想合并我的列表,但我需要传入一个虚拟初始值,这就是我想使用“foldr”的原因。

我目前的名单是:

[[(1, "Bob J", 4.0)],[(1, "Bill J", 2.5),(2,"Bill J", 2.7)]]

我想根据他们的名字组合列表,但在组合数字时我还需要做算术。

我当前的代码是:

grp xs = foldr combine xs
  where
    combine
    (x,_,y)
    (totalX,_,totalY)
    = (totalX+x,_,totalY+fromIntegral x *y)

这会返回一个错误。我希望 totalX 和 totalY 最初为零,这样它就不会影响计算。我该怎么做?

编辑:我希望我的输出采用相同的格式,所以我想要:

[(1,"Bob J", 4.0],(3,"Bill J", 2.6)]

【问题讨论】:

  • 您看到的错误是什么?
  • 看起来像group similar items in a list 的另一个变体...但我不确定是否可以作为骗子关闭,因为分组步骤似乎已经完成,只剩下组合步骤。即便如此,我仍然可能最终使用我在链接问题中建议的代码,除非这个问题之前的分组以某种方式在比 O(n log n) 时间更好的时间内完成。
  • 您只需要mapmap f = foldr ((:) . f) []
  • @WillNess 这并没有详细说明如何组合元素。
  • @TheInternet small 步骤... OP 会从那个小提示中找到解决方案,或者他们总是可以要求澄清。 :)

标签: list haskell tuples fold


【解决方案1】:

首先我会展平您的列表(使用concat),然后将这些值递归地累积到Map 中。在累积时,我会确保您通过加法来更新现有值(这就是 add 函数所做的)。

module Main where                                                                                                                                             

import           Data.List                                                                                                                                    
import qualified Data.Map  as M                                                                                                                               

main = print $ makeMap vals                                                                                                                                   

makeMap :: (Ord k, Num a, Num b) => [(a, k, b)] -> M.Map k (a, b)                                                                                             
makeMap = foldl' go mempty                                                                                                                                    
  where                                                                                                                                                       
    go m (x,name,y) = M.insertWith add name (x,y) m                                                                                                           
    add (a,b) (c,d) = (a+c,b+d)                                                                                                                               

vals = concat [[(1, "Bob J", 4.0)],[(1, "Bill J", 2.5),(2,"Bill J", 2.7)]]   

结果是

λ> main                                                                                                                                                       
fromList [("Bill J",(3,5.2)),("Bob J",(1,4.0))] 

【讨论】:

  • 在 O(n) 可能的情况下执行 O(n log n) 通常不是推荐的事情。这些组已经存在,您打算销毁它们,然后着手重新创建它们。
  • 我们可以使用可变哈希表来获得 O(n),但是是的 Map 插入是对数的。
  • 另外,需要明确的是,值本身并没有真正被破坏,GHC 将共享它们。 @WillNess
  • concat 'destroys' groups,就像忘记了 grouping
  • @WillNess 分组不是解决问题所必需的。另外,OP 明确表示他想根据名称组合列表,而不考虑分组。
猜你喜欢
  • 1970-01-01
  • 2013-01-11
  • 1970-01-01
  • 1970-01-01
  • 2021-12-20
  • 1970-01-01
  • 2021-03-02
  • 2013-03-11
  • 1970-01-01
相关资源
最近更新 更多