以任意长度数据作为键的函数式映射数据结构?

发布于 2024-10-31 20:04:30 字数 253 浏览 3 评论 0原文

这个问题的答案很可能是一个明显而响亮的“不存在这样的东西”,但我会尝试一下:是否存在一种功能性的类似地图的数据结构,在以下情况下比标准地图更有效:键的大小是任意的,通常非常大?

为了具体起见,请考虑 Haskell 类型,

(Ord k) => Map [k] v

如果列表需要深入比较,查找可能会花费很长时间。我想由于列表的任意长度,散列也是不可能的。我仍然情不自禁地认为可能存在一种聪明的数据结构。

It could very well be that the answer to this question is an obvious and resounding "there's no such thing", but I'll give it a shot: Is there a functional map-like data structure that is more efficient than a standard map when the keys have an arbitrary, often very big, size?

For the sake of concreteness, consider the Haskell type

(Ord k) => Map [k] v

in which lookups can take a very long time if lists need to be compared down to a deep level. I guess hashing is also out of the question due to the arbitrary length of the lists. I still can't help but think there could be a clever data structure out there.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

七色彩虹 2024-11-07 20:04:30

散列是不可能的吗?没有可以高效计算的关键结构的前缀吗?

如果没有,那么哈希图怎么样?将非常大的键减少到非常小的值,将其用作结构的索引。

Is hashing out of the question? There's no prefix of the key structure that can be computed efficiently?

If not, how about a hashmap? Take the very big key, reduce it to something very small, use that as an index into a structure.

标点 2024-11-07 20:04:30

特里树?

如果您有两个几乎相同的长键,则 Map 将从头开始比较它们,但 trie 只会比较先前比较中尚未消除的后缀(如果您明白我的意思)。所以在这种情况下,trie 会更省时。

尝试可以通过多种方式进行优化,您可能还想看看三元树。

A trie?

If you have two long keys that are almost identical, a Map will compare them both from the beginning, but a trie will only compare the suffixes that haven't already been eliminated by previous comparisons (if you see what I mean). So a trie would be more time-efficient in that situation.

Tries can be optimised in various ways, and you might also want to look at ternary trees.

瑾夏年华 2024-11-07 20:04:30

这是一个:

module ListMap where
import Data.Map as M

data ListMap k v = ListMap { ifEmpty :: Maybe v, ifFull :: Maybe k (ListMap k v) }

empty :: ListMap k v
empty = ListMap Nothing M.empty

singleton :: [k] -> v -> ListMap k v
singleton [] v = ListMap.empty { ifEmpty = Just v }
singleton (k:ks) v = ListMap.empty { ifFull = M.singleton k (ListMap.singleton ks v) }

lookup :: Ord k => [k] -> ListMap k v -> Maybe v
lookup [] lm = ifEmpty lm
lookup (k:ks) lm = M.lookup k (ifFull lm) >>= ListMap.lookup ks

insert :: Ord k => [k] -> v -> ListMap k v -> ListMap k v
insert [] v lm = lm { ifEmpty = Just v }
insert (k:ks) v lm = lm { ifFull = M.alter (Just . insertion) k (ifFull lm) }
  where insertion = maybe (ListMap.singleton ks v) (ListMap.insert ks v)

它本质上是在列表元素上创建一个前缀树,因此您只需进行必要的比较。

Here's one:

module ListMap where
import Data.Map as M

data ListMap k v = ListMap { ifEmpty :: Maybe v, ifFull :: Maybe k (ListMap k v) }

empty :: ListMap k v
empty = ListMap Nothing M.empty

singleton :: [k] -> v -> ListMap k v
singleton [] v = ListMap.empty { ifEmpty = Just v }
singleton (k:ks) v = ListMap.empty { ifFull = M.singleton k (ListMap.singleton ks v) }

lookup :: Ord k => [k] -> ListMap k v -> Maybe v
lookup [] lm = ifEmpty lm
lookup (k:ks) lm = M.lookup k (ifFull lm) >>= ListMap.lookup ks

insert :: Ord k => [k] -> v -> ListMap k v -> ListMap k v
insert [] v lm = lm { ifEmpty = Just v }
insert (k:ks) v lm = lm { ifFull = M.alter (Just . insertion) k (ifFull lm) }
  where insertion = maybe (ListMap.singleton ks v) (ListMap.insert ks v)

It's essentially creating a prefix tree on the list elements so you only compare as far as necessary.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文