在C ++和其他语言中,附加库实现了一个多索引容器,例如: Boost.Multiindex。也就是说,一个集合存储一种类型的值,但在这些值上保持多个不同的索引。这些索引提供不同的访问方法和排序行为,例如, map,multimap,set,multiset,array等。多索引容器的运行时复杂性通常是各个索引复杂性的总和。
是否存在Haskell的等价物或者人们自己编写?具体来说,使用set-type索引(T是Ord
的实例)以及map类型的索引(假设键值)实现类型T集合的最惯用方法是什么?可以为每个T提供类型K,可以是明确地还是通过函数T -> K
)?
答案 0 :(得分:7)
我今天上午刚刚将IxSet上传到hackage,
http://hackage.haskell.org/package/ixset
ixset提供具有多个索引的集合。
ixset已经存在了很长一段时间,因为我很快乐。此版本删除了特定于happstack的任何依赖项,并且是IxSet的新官方版本。
另一种选择是kdtree:
darcs获得http://darcs.monoid.at/kdtree
kdtree旨在通过提供更高的类型安全性和更好的时间和空间使用来改进IxSet。当前版本似乎在所有这三个方面都做得很好 - 但它尚未准备好迎接黄金时段。其他贡献者将受到高度欢迎。
答案 1 :(得分:6)
在每个元素都有一个始终可用的唯一键的简单情况下,您可以使用Map
并提取键来查找元素。在稍微不那么简单的情况下,每个值只有 一个密钥可用,一个简单的解决方案就像Map K (Set T)
。直接查找元素将涉及首先提取密钥,索引Map
以找到共享该密钥的元素集,然后查找所需的元素。
在大多数情况下,如果可以通过上述方式(简单的转换和嵌套)直接进行某些操作,那么以这种方式进行操作可能是有意义的。然而,由于显而易见的原因,这些都不能很好地概括为例如可能不可用的多个独立密钥或密钥。
除此之外,我不知道任何广泛使用的标准实现。确实存在一些例子,例如IxSet from happstack似乎大致符合法案。我怀疑这种大小适中的解决方案可能会带来很差的收益/复杂度,因此人们倾向于自己推出以满足特定需求。
直观地说,这似乎是一个问题,可能更好地工作,而不是作为单个实现,而是可以比Data.Map
允许更灵活地组成的基元集合,以创建特殊的专用结构。但这对短期需求并没有多大帮助。
答案 2 :(得分:4)
对于此特定问题,您可以使用Bimap。但是,一般情况下,我不知道多图或多索引容器的任何常见类。
答案 3 :(得分:2)
我认为最简单的方法就是使用Data.Map。虽然它被设计为使用单个索引,但是当您多次插入相同的元素时,大多数编译器(当然GHC)会将值放在同一个位置。多图的单独实现效率不高,因为你想根据它们的索引找到元素,所以你不能天真地将每个元素与多个索引相关联 - 比如[([key], value)]
- 因为这样效率非常低。 / p>
但是,我没有看过Multimaps的Boost实现,最后确定是否存在这样做的优化方法。
答案 4 :(得分:2)
我是否直接遇到了问题? T和K都有订单。有一个功能键:: T - > K但它不是保留订单。期望通过T顺序和K顺序管理Ts的集合,索引(用于快速访问)。更一般地,人们可能想要由一堆订单key1 :: T - >索引的T元素的集合。 K1,... keyn :: T - > Kn,碰巧这里key1 = id。那是图片吗?
我认为我同意gereeter的建议,即解决方案的基础只是保持同步一堆(Map K1 T,.. Map Kn T)。在映射中插入键值对既不会复制键也不会复制值,只会分配在索引中的正确位置创建新条目所需的额外堆。在多个索引中插入适当键入的相同值不应该破坏共享(即使其中一个键是值)。值得在API中包装结构,以确保对值的任何后续修改都计算一次并共享,而不是为索引中的每个条目重新计算。
底线:应该可以维护多个地图,确保共享这些值,即使按键顺序是分开的。