Erlang:erl shell在构建大型数据结构后挂起

Erlang:erl shell在构建大型数据结构后挂起,erlang,Erlang,正如在对的回答中所建议的,我尝试使用Erlangproplists来实现前缀trie 代码似乎运行得很好。。。但是,由于某些原因,它不能很好地与交互式shell配合使用。当我尝试运行它时,shell挂起: > Trie = trie:from_dict(). % Creates a trie from a dictionary % ... the trie is printed ... % Then nothing happens 问题是(除其他外?--请看我的评论)您总是在向proplist尝

正如在对的回答中所建议的,我尝试使用Erlang
proplist
s来实现前缀trie

代码似乎运行得很好。。。但是,由于某些原因,它不能很好地与交互式shell配合使用。当我尝试运行它时,shell挂起:

> Trie = trie:from_dict(). % Creates a trie from a dictionary % ... the trie is printed ... % Then nothing happens 问题是(除其他外?--请看我的评论)您总是在向proplist尝试添加一个新的{Ch,NewSubTrie}元组,不管Ch是否已经存在

而不是

NewTrie = [ { Ch, NewSubTrie } | Trie ]
你需要像这样的东西:

NewTrie = lists:keystore(Ch, 1, Trie, {Ch, NewSubTrie})

你不是真的在这里建一个trie。您的最终结果实际上是一个随机排序的proplist,在遍历列表时需要在每个级别进行完整扫描。尝试通常是基于数组(或列表)中的位置的隐含排序

下面是一个使用元组作为存储机制的实现。调用集仅重建根路径元组和直接路径元组。
(注意:可能需要将该对设置为三元组(增加大小)才能使delete以任何效率工作)

我相信erlang元组实际上只是数组(我想我在什么地方读过),所以查找应该非常快,修改可能是直接的。也许使用阵列模块会更快,但我还没有真正使用过它

此版本还存储任意值,因此您可以执行以下操作:

1> c(trie).
{ok,trie}
2>  trie:get("ab",trie:set("aa",bar,trie:new("ab",foo))). 
foo
3> trie:get("abc",trie:set("aa",bar,trie:new("ab",foo))).
undefined
4>
代码(整个模块):注2:假定小写非空字符串键

-module(trie).
-compile(export_all).
-define(NEW,{ %% 26 pairs, to avoid cost of calculating a new level at runtime
 {undefined,nodepth},{undefined,nodepth},{undefined,nodepth},{undefined,nodepth},
 {undefined,nodepth},{undefined,nodepth},{undefined,nodepth},{undefined,nodepth},
 {undefined,nodepth},{undefined,nodepth},{undefined,nodepth},{undefined,nodepth},
 {undefined,nodepth},{undefined,nodepth},{undefined,nodepth},{undefined,nodepth},
 {undefined,nodepth},{undefined,nodepth},{undefined,nodepth},{undefined,nodepth},
 {undefined,nodepth},{undefined,nodepth},{undefined,nodepth},{undefined,nodepth},
 {undefined,nodepth},{undefined,nodepth}
 }
).
-define(POS(Ch), Ch - $a + 1).

new(Key,V) -> set(Key,V,?NEW).

set([H],V,Trie) -> 
 Pos = ?POS(H),
 {_,SubTrie} = element(Pos,Trie),
 setelement(Pos,Trie,{V,SubTrie});

set([H|T],V,Trie) ->
 Pos = ?POS(H),
 {SubKey,SubTrie} = element(Pos,Trie),
 case SubTrie of
  nodepth -> setelement(Pos,Trie,{SubKey,set(T,V,?NEW)});
  SubTrie -> setelement(Pos,Trie,{SubKey,set(T,V,SubTrie)})
 end.

get([H],Trie) -> 
 {Val,_} = element(?POS(H),Trie),
 Val;
get([H|T],Trie) ->
 case element(?POS(H),Trie) of
  {_,nodepth} -> undefined;
  {_,SubTrie} -> get(T,SubTrie)
 end.

您可能误解了
proplist:compact()
。它只是用
Key
替换
{Key::atom(),'true'}
元组。别碰任何东西。噢!这就是我没有足够仔细的RTFMing所得到的。现在一切似乎都运行良好-谢谢。您可以用以下内容替换那个丑陋的宏:
new()->erlang:make_tuple(26,{undefined,nodepth})。
。POS也可以是一种功能。。。我想我只是讨厌宏:哦)哈!这就是它的名字。我不记得如何创建这样的元组,我懒得去查找它,是的,所有的东西都可以成为一个函数,我只是尝试优化一点,考虑到他的目标(构建一个包含很多单词的地图)。可能是我的一个愚蠢的早期优化
-module(trie).
-compile(export_all).
-define(NEW,{ %% 26 pairs, to avoid cost of calculating a new level at runtime
 {undefined,nodepth},{undefined,nodepth},{undefined,nodepth},{undefined,nodepth},
 {undefined,nodepth},{undefined,nodepth},{undefined,nodepth},{undefined,nodepth},
 {undefined,nodepth},{undefined,nodepth},{undefined,nodepth},{undefined,nodepth},
 {undefined,nodepth},{undefined,nodepth},{undefined,nodepth},{undefined,nodepth},
 {undefined,nodepth},{undefined,nodepth},{undefined,nodepth},{undefined,nodepth},
 {undefined,nodepth},{undefined,nodepth},{undefined,nodepth},{undefined,nodepth},
 {undefined,nodepth},{undefined,nodepth}
 }
).
-define(POS(Ch), Ch - $a + 1).

new(Key,V) -> set(Key,V,?NEW).

set([H],V,Trie) -> 
 Pos = ?POS(H),
 {_,SubTrie} = element(Pos,Trie),
 setelement(Pos,Trie,{V,SubTrie});

set([H|T],V,Trie) ->
 Pos = ?POS(H),
 {SubKey,SubTrie} = element(Pos,Trie),
 case SubTrie of
  nodepth -> setelement(Pos,Trie,{SubKey,set(T,V,?NEW)});
  SubTrie -> setelement(Pos,Trie,{SubKey,set(T,V,SubTrie)})
 end.

get([H],Trie) -> 
 {Val,_} = element(?POS(H),Trie),
 Val;
get([H|T],Trie) ->
 case element(?POS(H),Trie) of
  {_,nodepth} -> undefined;
  {_,SubTrie} -> get(T,SubTrie)
 end.