【问题标题】:Is there a standard name for this operation?此操作有标准名称吗?
【发布时间】:2015-12-27 08:50:42
【问题描述】:

所以在处理 Haskell 项目时,我最终编写了以下函数

reGrid :: [[[a]]] -> [[a]]
reGrid [] = []
reGrid xs | any null xs = []
          | otherwise = (concat $ map head xs) : reGrid (map tail xs)

对于那些不会说 Haskell 的人,这需要一个矩阵列表,并将相应的行连接到一个新矩阵中。

在这个项目中出现了好几次,我感觉这是我错过的某种常见操作。

此操作有标准名称吗?搜索 Hoogle

[[[a]]] -> [[a]

没有任何用处。

【问题讨论】:

    标签: haskell functional-programming list-processing


    【解决方案1】:

    您的功能与此功能非常相似(但不完全相同):

    reGrid' = map concat . transpose
    

    例如,我的 QuickCheck 属性 \xs -> reGrid xs == reGrid' xs 出现了这种差异:

    *Main> reGrid [[[]],[]]
    []
    *Main> reGrid' [[[]],[]]
    [[]]
    

    简而言之,您的版本将“删除”更多您可能真正关心(或不关心)的内容。举个更有说服力的例子:

    *Main> reGrid [["abc"],[]]
    []
    *Main> reGrid' [["abc"],[]]
    ["abc"]
    

    您可以自己判断它们不同的情况是否对您很重要。

    【讨论】:

      【解决方案2】:

      你有一堆东西,你想把它们变成一个东西。通常的方法是使用某种折叠。所以让我们开始吧:

      regrid [] = []
      regrid xs = foldr go (repeat []) xs
      

      现在假设你有一个矩阵,你也有重新网格化其余部分的结果。你怎么能把它们结合起来?好吧,您想将行合并在一起,直到一个行用完,这听起来像是 zipWith 的工作。所以把所有东西放在一起,

      regrid = foldr (zipWith (++)) []
      

      这不是一个标准函数,但它很短,并且不会乱用偏函数。但是,如果列表很长,它确实存在效率问题。要解决这个问题,您可以切换到左折叠,但要正确设置严格性会很棘手。我可以稍后再写。

      【讨论】:

      • 正是我想要的。需要注意的一点是,您的初始值必须是列表列表,长度与输入列表相等,否则它实际上不会到达任何行,即let reGrid2 xs = foldr (zipWith (++)) (replicate (length xs) []) xs
      • @user2085282,已修复,但有所不同。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-12-05
      • 2018-04-11
      • 2012-05-05
      • 1970-01-01
      • 2021-05-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多