list - 如何在 Haskell 中重构列表?

标签 list haskell transformation

我有一个这样的列表:(伪符号)

(X,...) -> (X,...) -> (X,...) -> ...
   |          |          |
   V          V          V
(Y,...)    (Y,...)    (Y,...)
   |          |          |
   V          V          V
(Z,...)    (Z,...)    (Z,...)

类型为(Enum a, Bounded a) => [[(a,x)]]。但我需要这样的东西:

(X, ... -> ... -> ... -> ...
   |
   V
(Y, ... -> ... -> ... -> ...
   |
   V
(Z, ... -> ... -> ... -> ...

类型类似于(Enum a, Bounded a) => [(a,[x])]

x 具有任意数量的元素。可以假设,x 的每个成员都是第一个列表的每个子列表中的键。

这种转换如何作为惰性 Haskell 算法实现(List 不需要完全评估即可返回(部分)结果)?

测试数据

参见上面,类似这样的内容:

--Input
[[(Foo,1),(Bar,1),(Baz,1)],[(Foo,2),(Bar,2),(Baz,2)],...]

--Output
[(Foo,[1,2,3,...]),(Bar,[1,2,3,...),(Baz,[1,2,3,...])]

我想用数据做什么

我想在这样的函数中使用它:

myFunc :: [(MyEnum,[Int])]
myFunc x@((_,(_:[])):_) = x
myFunc x            = foldTheListRecursively

该函数必须处理大量数据(每个枚举约 10'000 个条目),该列表应该可由运行时系统进行垃圾收集(该列表是由程序的另一部分临时构建的)

我的(丑陋的)实现

是这样的,我实现了,但是显然不符合要求,因为列表被遍历了多次:

restructList :: [[(a,x)]] -> [(a,[x])]
resturctList list = (\x -> (x,listFor x)) <$> keys where
  keys = fst <$> head list
  listFor x = snd <$> any ((==x).fst) <$> list

我不在家,无法测试,所以可能会有错误。

最佳答案

一些示例数据会让您的问题更容易理解。我假设给定一个如下列表:

input = [[("foo", 1), ("foo", 2)], [("bar", 3), ("bar", 4)]]

你想要得到

output = [("foo",[1,2]), ("bar",[3,4])]

如果是这样,首先想到的是 Data.Map.insertWith。这就像创建从键到值的映射,除非该值已存在,您指定的函数将应用于当前值和新值,并插入结果

例如,如果我们写:

import qualified Data.Map as M
step0 = M.insertWith (++) "key" ["value"] M.empty

那么step0只是一个将键映射到值的映射。但如果我们再次调用它:

step1 = M.insertWith (++) "key" ["OH HAI"] step0

现在我们有了一个从键到["value","OH HAI"]的映射。这几乎正​​是您想要的,但是您需要一些枚举/有界列表,而不是字符串列表。

因此,第一步是获取数据的一个“行”,并将其添加到 map 中:

import qualified Data.List as L
toMap1 :: M.Map a b -> [(a,b)] -> M.Map a b
toMap1 = L.foldr (λ(k,v) m → M.insertWith (++) k [v] m)

给出从最顶部开始的 input 的第一个元素,您将得到:

toMap M.empty (head input)
    ==> [("foo",[1,2])]

现在我们只需要将每一行累积到该映射中,而不仅仅是第一行。这只是另一种折叠:

toMap2 :: [[(a,b)]] -> Map a b
toMap2 = L.foldr (flip toMap1) M.empty

现在你可以写:

toMap2 input

并得到:

fromList [("bar",[3,4]),("foo",[1,2])]

一个简单的M.toList将其转换回常规列表,从而产生输出

关于list - 如何在 Haskell 中重构列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3718723/

相关文章:

c - 从文件中逐行读取并保存在列表中 C

python - 从Python中的链表中删除一个元素

list - 为什么Buffer和List对象相等(即使它们来自不同的类)?

haskell - 这 ? emacs/haskell 和 ghc 模式下的标记

r - 如何将单列列表转换为 R 中的项目矩阵?

c++ - 透视世界空间逆投影

java - 在 Java 中从行集创建树的最佳方法

string - 连接函数在哪里?

haskell - 如何在状态 monad 中使用 Debug.Trace.trace?

jquery - 滚动时的 CSS3 转换